import java.security.NoSuchAlgorithmException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Properties;
import java.util.TimeZone;

import javax.mail.MessagingException;
import javax.mail.SendFailedException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

/**
 * @author Bastiaan Grutters
 *
 */
public class Database extends Thread {
	private final static long DELAY = 1000;

	private AgesOfStrifeServer parent;
	private Translations translations;
	private NewsItem newsItem;
	private int speed;
	private int countDown;
	private int turn;
	private int maxTurn;
	private int extra_turns;
	private int special_event_started;
	private int special_event_initialized;
	//private int global_orders;
	private int season;
	private String date;
	private boolean running;
	private ResultSet rs, rs2, rs3, rs4;
	private Statement stmt, stmtUpdate, stmt2, stmt3, stmt4;
	private Connection con;
	private int[] rulers;
	private int[] building_id, building_coal_income, building_iron_income, building_food_income, building_jobs, building_gold_cost, building_time_cost, building_requires, building_upgrades, building_space, building_construction_jobs, building_allowed, building_housing;
	private double[] building_growth, building_defense_bonus, building_offense_bonus;
	private GregorianCalendar calendar = new GregorianCalendar();
	
	public Database( AgesOfStrifeServer parent ) {
		this.parent = parent;
		Statement stmt;
		ResultSet rs;
		try {
			Connection con = getConnection();
			
			stmt = con.createStatement();
			stmt4 = con.createStatement();
			rs = stmt.executeQuery( "SELECT * FROM game" );
			while( rs.next() ) {
				turn = rs.getInt( "turn" );
				//parent.setTurn( turn );
				maxTurn = rs.getInt( "max_turn" );
				extra_turns = rs.getInt( "extra_turns" );
				//global_orders = rs.getInt( "global_orders" );
				special_event_started = rs.getInt( "special_event_started" );
				special_event_initialized = rs.getInt( "special_event_initialized" );
				season = rs.getInt( "season" );
				//parent.setMaxTurn( maxTurn );
				speed = countDown = rs.getInt( "speed" );
				//parent.setSpeed( speed );
			}
			
			stmt = con.createStatement();
			rs = stmt.executeQuery( "SELECT count(*) FROM users" );
			rs.next();
			int userCount = rs.getInt( 1 );
			//parent.setUserCount( userCount );
			
			stmt = con.createStatement();
			rs = stmt.executeQuery( "SELECT count(*) FROM ruler" );
			rs.next();
			int rulerCount = rs.getInt( 1 );
			//parent.setRulerCount( rulerCount );
			con.close();
			AgesOfStrifeServer.log.info( "There are currently: " + rulerCount + " rulers and " + userCount + " users." );
			
		} catch ( SQLException e ) {
			AgesOfStrifeServer.log.error( e.getStackTrace() );
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			AgesOfStrifeServer.log.error( getStackError( e ) );
			e.printStackTrace();
		}
		
		//parent.setStatus( "Ready and waiting." );
	}
	
	private String getStackError( Exception exception ) {
		String errorMessage = "";
		StackTraceElement[] stackTraceElements = exception.getStackTrace(); 
		
		for( int i = 0; i < stackTraceElements.length; i ++ ) {
			errorMessage += stackTraceElements[i].toString() + " - " + stackTraceElements[i].getLineNumber() + "\r\n";
		}
		
		return errorMessage;
	}
	
	public void run() {
		long sleep = DELAY;
		while ( running ) {
			try {
				if( sleep > 0 ) {
					sleep( sleep );
				}
			} catch ( InterruptedException ie ) {
				// We are interrupted, probably process killed
			}
			sleep = System.currentTimeMillis();
			//parent.setCountDown( countDown );
			countDown --;
			if( countDown == 0 ) {
				boolean gameIsRunning = false;
				try {
					AgesOfStrifeServer.log.debug( "Connecting to DB..." );
					con = getConnection();
					con.setAutoCommit( false );
					translations = new Translations( con );
					translations.setLocation( "/news/news.php" );
					newsItem = new NewsItem( con, translations );
					stmt = con.createStatement();
					stmtUpdate = con.createStatement();
					stmt2 = con.createStatement();
					stmt3 = con.createStatement();
					stmt4 = con.createStatement();
					rs = stmt.executeQuery( "SELECT game_running, start_time, special_event_started " +
							"FROM game" );
					rs.next();
					gameIsRunning = ( rs.getInt( "game_running" ) == 1 );
					special_event_started = rs.getInt( "special_event_started" );
					int startTime = rs.getInt( "start_time" );
					if( !gameIsRunning && startTime > 0 ) {
						AgesOfStrifeServer.log.debug( "The game is not running, we have to check if the start date already passed..." );
						TimeZone timeZone = TimeZone.getTimeZone( "Amsterdam" );
						GregorianCalendar gregorianCalendar = new GregorianCalendar( timeZone ); 
						Date now = gregorianCalendar.getTime();
						gregorianCalendar.setTimeInMillis( startTime * 1000l );
						Date startDate = gregorianCalendar.getTime();
						AgesOfStrifeServer.log.debug( "It is now: " + now + " and we have to start at " + startDate );
						if( startDate.before( now ) ) {
							AgesOfStrifeServer.log.debug( "So it did, so we mark the game as running." );
							gameIsRunning = true;
							stmtUpdate.execute( "UPDATE game " +
									"SET game_running = 1" );
						}
					}
				} catch( SQLException sqlException ) {
					AgesOfStrifeServer.log.error( "There was a SQL error trying to connect to the database." );
				} catch (ClassNotFoundException e) {
					AgesOfStrifeServer.log.error( "There was a class not found error trying to connect to the database." );
				}
				
				//parent.setTurn( turn );
				if( turn >= maxTurn && special_event_started == 0 ) {
					countDown = speed;
					AgesOfStrifeServer.log.info( "Game round is over, but special event can be started." );
					countDown = countDown - ( int ) ( System.currentTimeMillis() * 0.001 % countDown );
				}
				else if( turn >= maxTurn + extra_turns ) {
					countDown = speed;
					AgesOfStrifeServer.log.info( "The round is really over... seriously!" );
					countDown = countDown - ( int ) ( System.currentTimeMillis() * 0.001 % countDown );
				}
				else {
					countDown = speed;
					if( gameIsRunning ) {
						if( turn > maxTurn && special_event_initialized == 0 ) {
							initializeSpecialEvent();
						}
						turn ++;
						update();
					}
					countDown = countDown - ( int ) ( System.currentTimeMillis() * 0.001 % countDown );
				}
			}
			sleep += ( DELAY - System.currentTimeMillis() ); 
		}
	}
	
	private void initializeSpecialEvent() {
		try {
			int minX = 0;
			int maxX = 0;
			int minY = 0;
			int maxY = 0;
			long scouts = 0;
			long infantry = 0;
			long cavalry = 0;
			long artillery = 0;
			double devideBy = 1;
			rs = stmt.executeQuery( "SELECT max(x), max(y) " +
					"FROM village" );
			rs.next();
			maxX = rs.getInt( 1 );
			maxY = rs.getInt( 2 );
			
			rs = stmt.executeQuery( "SELECT SUM(scout), SUM(infantry), SUM(cavalry), SUM(artillery) " +
				"FROM army" );
			rs.next();
			scouts = rs.getLong( 1 );
			infantry = rs.getLong( 2 );
			cavalry = rs.getLong( 3 );
			artillery = rs.getLong( 4 );
			rs = stmt.executeQuery( "SELECT SUM(scouts), SUM(infantry), SUM(cavalry), SUM(artillery) " +
				"FROM ruler" );
			rs.next();
			scouts += rs.getLong( 1 );
			infantry += rs.getLong( 2 );
			cavalry += rs.getLong( 3 );
			artillery += rs.getLong( 4 );
			rs = stmt.executeQuery( "SELECT SUM(scouts), SUM(infantry), SUM(cavalry), SUM(artillery) " +
				"FROM transfer" );
			rs.next();
			scouts += rs.getLong( 1 );
			infantry += rs.getLong( 2 );
			cavalry += rs.getLong( 3 );
			artillery += rs.getLong( 4 );
			
			devideBy = ( maxX * 0.1 );  
			
			scouts = ( long ) ( scouts / devideBy );
			if( scouts > 906250 ) {
				scouts = 906250;
			}
			else if( scouts < 90625 ) {
				scouts = 90625;
			}
			
			infantry = ( long ) ( infantry / devideBy );
			if( infantry > 2000000 ) {
				infantry = 2000000;
			}
			else if( infantry < 200000 ) {
				infantry = 200000;
			}
			cavalry = ( long ) ( cavalry / devideBy );
			if( cavalry > 500000 ) {
				cavalry = 500000;
			}
			else if( cavalry < 50000 ) {
				cavalry = 50000;
			}
			artillery = ( long ) ( artillery / devideBy );
			if( artillery > 500000 ) {
				artillery = 500000;
			}
			else if( artillery < 50000 ) {
				artillery = 50000;
			}
				
			int mode = ( int ) Math.round( Math.random() * 4.0 );
			if( mode == 0 ) {
				// Attacks will come form the north
				for( int i = minX; i < maxX; i ++ ) {
					String officerName = "Invader " + ( i + 1 );
					stmtUpdate.execute( "INSERT INTO officers " +
							"( `name`, `ruler_id`, `rank`, `ranking` ) " +
							"VALUES( '" + officerName + "', -1, 7, 5 )" );
					rs = stmt.executeQuery( "SELECT officer_id " +
							"FROM officers " +
							"WHERE name = '" + officerName + "' AND ruler_id = -1" );
					if( rs.next() ) {
						int officer_id = rs.getInt( "officer_id" );
						stmtUpdate.execute( "INSERT INTO army " +
								"( `name`, `officer_id`, `ruler_id`, `scout`, `infantry`, `cavalry`, `artillery`, `x`, `y`, `actual_x`, `actual_y`, `instructions` ) " +
								"VALUES( 'Invasion Force " + ( i + 1 ) + "', " + officer_id + ", -1, " + scouts + ", " + infantry + ", " + cavalry + ", " + artillery + ", " + i + ", " + minY + ", " + i + ", " + minY + ", 2 )" );
					}
				}
			}
			else if( mode == 1 ) {
				// Attacks will come form the west
				for( int i = minY; i < maxY; i ++ ) {
					String officerName = "Invader " + ( i + 1 );
					stmtUpdate.execute( "INSERT INTO officers " +
							"( `name`, `ruler_id`, `rank`, `ranking` ) " +
							"VALUES( '" + officerName + "', -1, 7, 5 )" );
					rs = stmt.executeQuery( "SELECT officer_id " +
							"FROM officers " +
							"WHERE name = '" + officerName + "' AND ruler_id = -1" );
					if( rs.next() ) {
						int officer_id = rs.getInt( "officer_id" );
						stmtUpdate.execute( "INSERT INTO army " +
								"( `name`, `officer_id`, `ruler_id`, `scout`, `infantry`, `cavalry`, `artillery`, `x`, `y`, `actual_x`, `actual_y`, `instructions` ) " +
								"VALUES( 'Invasion Force " + ( i + 1 ) + "', " + officer_id + ", -1, " + scouts + ", " + infantry + ", " + cavalry + ", " + artillery + ", " + minX + ", " + i + ", " + minX + ", " + i + ", 2 )" );
					}
				}
			}
			/*else if( mode == 2 ) {
				// Attacks will come form the south
				for( int i = minX; i < maxX; i ++ ) {
					String officerName = "Invader " + ( i + 1 );
					stmtUpdate.execute( "INSERT INTO officers " +
							"( `name`, `ruler_id`, `rank`, `ranking` ) " +
							"VALUES( '" + officerName + "', -1, 7, 5 )" );
					rs = stmt.executeQuery( "SELECT officer_id " +
							"FROM officers " +
							"WHERE name = '" + officerName + "' AND ruler_id = -1" );
					if( rs.next() ) {
						int officer_id = rs.getInt( "officer_id" );
						stmtUpdate.execute( "INSERT INTO army " +
								"( `name`, `officer_id`, `ruler_id`, `scout`, `infantry`, `cavalry`, `artillery`, `x`, `y`, `actual_x`, `actual_y`, `instructions` ) " +
								"VALUES( 'Invasion Force " + ( i + 1 ) + "', " + officer_id + ", -1, 906250, 2000000, 500000, 500000, " + i + ", " + maxY + ", " + i + ", " + maxY + ", 2 )" );
					}
				}
			}*/
			else if( mode == 2 ) {
				// Attacks will come form the east
				for( int i = minY; i < maxY; i ++ ) {
					String officerName = "Invader " + ( i + 1 );
					stmtUpdate.execute( "INSERT INTO officers " +
							"( `name`, `ruler_id`, `rank`, `ranking` ) " +
							"VALUES( '" + officerName + "', -1, 7, 5 )" );
					rs = stmt.executeQuery( "SELECT officer_id " +
							"FROM officers " +
							"WHERE name = '" + officerName + "' AND ruler_id = -1" );
					if( rs.next() ) {
						int officer_id = rs.getInt( "officer_id" );
						stmtUpdate.execute( "INSERT INTO army " +
								"( `name`, `officer_id`, `ruler_id`, `scout`, `infantry`, `cavalry`, `artillery`, `x`, `y`, `actual_x`, `actual_y`, `instructions` ) " +
								"VALUES( 'Invasion Force " + ( i + 1 ) + "', " + officer_id + ", -1, " + scouts + ", " + infantry + ", " + cavalry + ", " + artillery + ", " + maxX + ", " + i + ", " + maxX + ", " + i + ", 2 )" );
					}
				}
			}
			else if( mode == 3 ) {
				// Attacks will come form everywhere
				int count = 0;
				for( int i = minX; i < maxX; i += 4 ) {
					String officerName = "Invader " + ( count + 1 );
					stmtUpdate.execute( "INSERT INTO officers " +
							"( `name`, `ruler_id`, `rank`, `ranking` ) " +
							"VALUES( '" + officerName + "', -1, 7, 5 )" );
					rs = stmt.executeQuery( "SELECT officer_id " +
							"FROM officers " +
							"WHERE name = '" + officerName + "' AND ruler_id = -1" );
					if( rs.next() ) {
						int officer_id = rs.getInt( "officer_id" );
						stmtUpdate.execute( "INSERT INTO army " +
								"( `name`, `officer_id`, `ruler_id`, `scout`, `infantry`, `cavalry`, `artillery`, `x`, `y`, `actual_x`, `actual_y`, `instructions` ) " +
								"VALUES( 'Invasion Force " + ( count + 1 ) + "', " + officer_id + ", -1, " + scouts + ", " + infantry + ", " + cavalry + ", " + artillery + ", " + i + ", " + minY + ", " + i + ", " + minY + ", 2 )" );
					}
					count ++;
					officerName = "Invader " + ( count + 1 );
					stmtUpdate.execute( "INSERT INTO officers " +
							"( `name`, `ruler_id`, `rank`, `ranking` ) " +
							"VALUES( '" + officerName + "', -1, 7, 5 )" );
					rs = stmt.executeQuery( "SELECT officer_id " +
							"FROM officers " +
							"WHERE name = '" + officerName + "' AND ruler_id = -1" );
					if( rs.next() ) {
						int officer_id = rs.getInt( "officer_id" );
						stmtUpdate.execute( "INSERT INTO army " +
								"( `name`, `officer_id`, `ruler_id`, `scout`, `infantry`, `cavalry`, `artillery`, `x`, `y`, `actual_x`, `actual_y`, `instructions` ) " +
								"VALUES( 'Invasion Force " + ( count + 1 ) + "', " + officer_id + ", -1, " + scouts + ", " + infantry + ", " + cavalry + ", " + artillery + ", " + i + ", " + maxY + ", " + i + ", " + maxY + ", 2 )" );
					}
					count ++;
				}
				for( int i = minY + 4; i < maxY; i += 4 ) {
					String officerName = "Invader " + ( count + 1 );
					stmtUpdate.execute( "INSERT INTO officers " +
							"( `name`, `ruler_id`, `rank`, `ranking` ) " +
							"VALUES( '" + officerName + "', -1, 7, 5 )" );
					rs = stmt.executeQuery( "SELECT officer_id " +
							"FROM officers " +
							"WHERE name = '" + officerName + "' AND ruler_id = -1" );
					if( rs.next() ) {
						int officer_id = rs.getInt( "officer_id" );
						stmtUpdate.execute( "INSERT INTO army " +
								"( `name`, `officer_id`, `ruler_id`, `scout`, `infantry`, `cavalry`, `artillery`, `x`, `y`, `actual_x`, `actual_y`, `instructions` ) " +
								"VALUES( 'Invasion Force " + ( count + 1 ) + "', " + officer_id + ", -1, " + scouts + ", " + infantry + ", " + cavalry + ", " + artillery + ", " + maxX + ", " + i + ", " + maxX + ", " + i + ", 2 )" );
					}
					count ++;
					officerName = "Invader " + ( count + 1 );
					stmtUpdate.execute( "INSERT INTO officers " +
							"( `name`, `ruler_id`, `rank`, `ranking` ) " +
							"VALUES( '" + officerName + "', -1, 7, 5 )" );
					rs = stmt.executeQuery( "SELECT officer_id " +
							"FROM officers " +
							"WHERE name = '" + officerName + "' AND ruler_id = -1" );
					if( rs.next() ) {
						int officer_id = rs.getInt( "officer_id" );
						stmtUpdate.execute( "INSERT INTO army " +
								"( `name`, `officer_id`, `ruler_id`, `scout`, `infantry`, `cavalry`, `artillery`, `x`, `y`, `actual_x`, `actual_y`, `instructions` ) " +
								"VALUES( 'Invasion Force " + ( count + 1 ) + "', " + officer_id + ", -1, " + scouts + ", " + infantry + ", " + cavalry + ", " + artillery + ", " + minX + ", " + i + ", " + minX + ", " + i + ", 2 )" );
					}
					count ++;
				}
				
				if( mode > 1 ) {
					mode ++;
				}
				stmtUpdate.execute( "UPDATE game " +
						"SET special_event_initialized = 1, global_orders = " + mode );
				special_event_initialized = 1;
			}
		} catch ( SQLException sqlException ) {
			AgesOfStrifeServer.log.error( getStackError( sqlException ) );
			sqlException.printStackTrace();
		}
	}

	public void startTurns() {
		running = true;
		countDown = countDown - ( int ) ( System.currentTimeMillis() * 0.001 % countDown );
		start();
	}
	
	public void stopTurns() {
		running = false;
	}
 
	public void update() {
		long timestamp = System.currentTimeMillis();
		try {
			AgesOfStrifeServer.log.debug( "Updating turn: " + turn );
			// set the date for this turn
			calendar.set( 1760, 2, 1 );
			calendar.add( GregorianCalendar.HOUR, turn * 24 );
			String day = "" + calendar.get( GregorianCalendar.DAY_OF_MONTH );
			String month = "" + ( calendar.get( GregorianCalendar.MONTH ) + 1 );
			if( day.length() == 1 ) {
				day = "0" + day;
			}
			if( month.length() == 1 ) {
				month = "0" + month;
			}
			
			date = day + "-" + month + "-" + calendar.get( GregorianCalendar.YEAR );
			
			boolean seasonChanged = false;
			String title = "";
			String text = "";
			
			if( season == 0 && month.equals( "03" ) ) {
				// Spring
				season = 1;
				title = "Spring";
				text = "The cold winter has finally come to an end, farmers return to the fields.\n" +
						"Food production are restored to normal.";
				seasonChanged = true;
			}
			else if( season == 1 && month.equals( "06" ) ) {
				// Summer
				season = 2;
				seasonChanged = true;
				title = "Summer";
				text = "Summer has come, farmers are preparing for the harvest.\n" +
						"Food production has doubled, food can be stockpiled for the winter.";
			}
			else if( season == 2 && month.equals( "09" ) ) {
				// Autumn
				season = 3;
				seasonChanged = true;
				title = "Autumn";
				text = "Days are getting shorter and colder, autumn has come.\n" +
						"Food production has decreased to normal.\n" +
						"Make sure you gather enough food so your population can make it through the winter.";
			}
			else if( season == 3 && month.equals( "12" ) ) {
				// Winter
				season = 0;
				seasonChanged = true;
				title = "Winter";
				text = "Winter has come, the land is covered in snow.\n" +
						"Food production has completely halted.\n" +
						"Hopefully you have enough food for the winter, else you might be able to trade for some more.";
			}
			
			if( seasonChanged ) {
				stmtUpdate.execute( "INSERT INTO history " +
						"( title, text, ruler_id, turn, date, visible ) " +
						"VALUES ( '" + title + "', '" + text + "', -1, " + turn + ", '" + date + "', 1 )" );
				rs = stmt.executeQuery( "SELECT history_id " +
						"FROM history " +
						"WHERE title = '" + title + "' AND text = '" + text + "' AND ruler_id = -1 AND turn = " + turn + " AND date = '" + date + "' " +
						"LIMIT 1" );
				int history_id = -1;
				if( rs.next() ) {
					history_id = rs.getInt( "history_id" );
					Utils.notifyOfHistory( rs, stmt, history_id );
				}
			}
			
			// get the current building list:
			
			rs = stmt.executeQuery( "SELECT count(*) " +
					"FROM buildings" );
			rs.next();
			int buildingsTotal = rs.getInt( 1 );
			
			building_coal_income = new int[buildingsTotal];
			building_iron_income = new int[buildingsTotal];
			building_food_income = new int[buildingsTotal];
			building_construction_jobs = new int[buildingsTotal];
			building_gold_cost = new int[buildingsTotal];
			building_growth = new double[buildingsTotal];
			building_id = new int[buildingsTotal];
			building_jobs = new int[buildingsTotal];
			building_requires = new int[buildingsTotal];
			building_space = new int[buildingsTotal];
			building_time_cost = new int[buildingsTotal];
			building_upgrades = new int[buildingsTotal];
			building_defense_bonus = new double[buildingsTotal];
			building_offense_bonus = new double[buildingsTotal];
			building_allowed = new int[buildingsTotal];
			building_housing = new int[buildingsTotal];
			
			rs = stmt.executeQuery( "SELECT * " +
					"FROM buildings" );
			
			for( int i = 0; i < buildingsTotal; i ++ ) {
				rs.next();
				building_coal_income[i] = rs.getInt( "coal_income" );
				building_iron_income[i] = rs.getInt( "iron_income" );
				building_food_income[i] = rs.getInt( "food_income" );
				building_construction_jobs[i] = rs.getInt( "construction_jobs" );
				building_gold_cost[i] = rs.getInt( "gold_cost" );
				building_growth[i]= rs.getDouble( "population_growth" );
				building_id[i] = rs.getInt( "building_id" );
				building_jobs[i] = rs.getInt( "jobs" );
				building_requires[i] = rs.getInt( "requires" );
				building_space[i] = rs.getInt( "space" );
				building_time_cost[i] = rs.getInt( "time_cost" );
				building_upgrades[i] = rs.getInt( "upgrade" );
				building_allowed[i] = rs.getInt( "ammount_allowed" );
				building_defense_bonus[i]= rs.getDouble( "defense_bonus" );
				building_offense_bonus[i]= rs.getDouble( "offense_bonus" );
				building_housing[i]= rs.getInt( "housing" );
			}
			
			stmtUpdate.execute( "UPDATE game " +
					"SET turn_update = 1" );
			con.commit();
			
			if( "01".equals( day ) && "01".equals( month ) ) {
				stmtUpdate.execute( "UPDATE ruler SET last_year_growth = ( ( score / last_year_score - 1 ) * 100 )" );
				con.commit();
				stmtUpdate.execute( "UPDATE ruler SET last_year_gold = year_gold, last_year_iron = year_iron, last_year_coal = year_coal, last_year_score = score" );
				con.commit();
				stmtUpdate.execute( "UPDATE ruler SET year_gold = 0, year_iron = 0, year_coal = 0" );
				
				// Write a top 5 of fastest growing rulers
				String txt = "<table class=\\\"onethird\\\"><tr><th colspan=\\\"4\\\">Rulers</th></tr>\n";
				rs = stmt.executeQuery( "SELECT name, ruler_id, score, last_year_growth " +
						"FROM ruler " +
						"ORDER BY last_year_growth DESC LIMIT 5" );
				int counter = 1;
				while( rs.next() ) {
					txt += "<tr><td>" + counter + ".</td><td><a href=\\\"../overview/ruler.php?name=" + rs.getString( "name" ) + "\\\">" + rs.getString( "name" ) + "</a></td>" +
							"<td align=\\\"right\\\">" + ( ( ( int ) Math.round( rs.getDouble( "last_year_growth" ) * 100.0 ) ) * 0.01 ) + "%</td>" +
							"<td align=\\\"right\\\">" + Utils.formatNumber( "" + rs.getLong( "score" ) ) + "</td></tr>";
					counter ++;
				}
				txt += "</table>";
				String subject = "Top " + ( counter - 1 ) + " fastest growing rulers";
				stmtUpdate.execute( "INSERT INTO history " +
						"( title, text, ruler_id, turn, date, visible ) " +
						"VALUES ( '" + subject + "', '" + txt + "', -1, " + turn + ", '" + date + "', 1 )" );
				rs = stmt.executeQuery( "SELECT history_id " +
						"FROM history " +
						"WHERE title = '" + subject + "' AND text = '" + txt + "' AND ruler_id = -1 AND turn = " + turn + " AND date = '" + date + "' " +
						"LIMIT 1" );
				int history_id = -1;
				if( rs.next() ) {
					history_id = rs.getInt( "history_id" );
				}
				Utils.notifyOfHistory( rs, stmt, history_id );
				
			}
			else {
				stmtUpdate.execute( "UPDATE ruler SET last_year_score = score WHERE last_year_score = 0 AND score > 0" );
			}
			
			handleArmyInstructions();
			
			if( turn > 0 && turn % 120 == 0 ) {
				updateNewBattlescore();
			}

			updateTrade();
			con.commit();
			
			updateExpeditons();
			con.commit();
			
			updateLoyalty();
			con.commit();
			
			rs = stmt.executeQuery( "SELECT turns_inactive FROM game" );
			rs.next();
			int turns_inactive = rs.getInt( "turns_inactive" );
			
			if( turn % 48 == 0 ) {
				rs = stmt.executeQuery( "SELECT count( ruler_id ) FROM ruler" );
			}
			else {
				rs = stmt.executeQuery( "SELECT count( ruler_id ) " +
						"FROM ruler " +
						"WHERE resigned = 0 AND active_turn > " + ( turn - turns_inactive ) );
			}
			rs.next();
			int total = rs.getInt( 1 );
			rulers = new int[total];
			int count = 0;
			
			// update each rulers stats
			stmt = con.createStatement();
			if( turn % 48 == 0 ) {
				rs = stmt.executeQuery( "SELECT ruler_id FROM ruler" );
			}
			else {
				rs = stmt.executeQuery( "SELECT ruler_id FROM ruler WHERE resigned = 0 AND active_turn > " + ( turn - turns_inactive ) );
			}
			while( rs.next() ) {
				rulers[count] = rs.getInt( "ruler_id" );
				count ++;
			}
			
			for( int i = 0; i < total; i ++ ) {
				updateRuler( rulers[i] );
			}
			updateArmies( -1, 0l );
			updateFollowingFatigue();
			con.commit();
			
			militiaLookingForAFight();			
			updateFactions();
			if( turn % 96 == 6 ) {
				updateDemocraticFactions();
			}
			con.commit();
			
			if( turn % 24 == 3 ) {
				updateFactionColors();
			}
			else if( turn % 24 == 2 ) {
				// Update spotlight village
				updateSpotlightVillage();
			}
			
			resolveBombardments();
			con.commit();
			resolveIdleArmies();
			con.commit();
			
			resolveCombat();
			con.commit();
			
			updateMilitaryMorale( turns_inactive );
			stmtUpdate.execute( "UPDATE officers SET experience = experience + 2" );
			stmtUpdate.execute( "UPDATE officers " +
					"SET experience = experience + 3 " +
					"WHERE officers.ruler_id = ( SELECT ruler.ruler_id FROM ruler " +
						"JOIN users ON ruler.user_id = users.user_id " +
						"WHERE premium > -1 AND ruler.ruler_id = officers.ruler_id )" );
			
			updateRaces();
			updateVisibleArmies( turns_inactive );
			checkForTaskProgress();
			updateWarriorPoints();
			updateEconomyPoints();
			
			updateCapitalChanges();
			
			if( turn > maxTurn ) { 
				conquerVillagesByIndependentArmies();
				updateIdleIndependentArmies();
			}
			
			if( turn % 30 == 0 || turn == 2 ) {
				storePremiumStats();
			}
			
			if( turn % 96 == 0 ) {
				// Write a report about ruler stats
				String txt = "<table class=\\\"onethird\\\"><tr><th colspan=\\\"3\\\">Rulers</th></tr>\n";
				rs = stmt.executeQuery( "SELECT * " +
						"FROM ruler " +
						"ORDER BY score DESC LIMIT 5" );
				int counter = 1;
				while( rs.next() ) {
					txt += "<tr><td>" + counter + ".</td><td><a href=\\\"../overview/ruler.php?name=" + rs.getString( "name" ) + "\\\">" + rs.getString( "name" ) + "</a></td><td align=\\\"right\\\">" + Utils.formatNumber( "" + rs.getLong( "score" ) ) + "</td></tr>";
					counter ++;
				}
				txt += "</table>";
				String subject = "Top " + ( counter - 1 ) + " rulers";
				stmtUpdate.execute( "INSERT INTO history " +
						"( title, text, ruler_id, turn, date, visible ) " +
						"VALUES ( '" + subject + "', '" + txt + "', -1, " + turn + ", '" + date + "', 1 )" );
				rs = stmt.executeQuery( "SELECT history_id " +
						"FROM history " +
						"WHERE title = '" + subject + "' AND text = '" + txt + "' AND ruler_id = -1 AND turn = " + turn + " AND date = '" + date + "' " +
						"LIMIT 1" );
				int history_id = -1;
				if( rs.next() ) {
					history_id = rs.getInt( "history_id" );
				}
				Utils.notifyOfHistory( rs, stmt, history_id );
			}
			else if( turn % 96 == 48 ) {
				// Write a report about faction stats
				String txt = "<table class=\\\"onethird\\\"><tr><th colspan=\\\"3\\\">Factions</th></tr>\n";
				rs = stmt.executeQuery( "SELECT * " +
						"FROM faction " +
						"ORDER BY score DESC LIMIT 5" );
				int counter = 1;
				while( rs.next() ) {
					txt += "<tr><td>" + counter + ".</td><td><a href=\\\"../overview/faction.php?name=" + rs.getString( "name" ) + "\\\">" + rs.getString( "name" ) + "</a></td><td align=\\\"right\\\">" + Utils.formatNumber( "" + rs.getLong( "score" ) ) + "</td></tr>";
					counter ++;
				}
				txt += "</table>";
				if( counter > 1 ) {
					String subject = "Top " + ( counter - 1 )+ " factions";
					stmtUpdate.execute( "INSERT INTO history " +
							"( title, text, ruler_id, turn, date, visible ) " +
							"VALUES ( '" + subject + "', '" + txt + "', -1, " + turn + ", '" + date + "', 1 )" );
					rs = stmt.executeQuery( "SELECT history_id " +
							"FROM history " +
							"WHERE title = '" + subject + "' AND text = '" + txt + "' AND ruler_id = -1 AND turn = " + turn + " AND date = '" + date + "' " +
							"LIMIT 1" );
					int history_id = -1;
					if( rs.next() ) {
						history_id = rs.getInt( "history_id" );
					}
					Utils.notifyOfHistory( rs, stmt, history_id );
				}
			}
			
			if( turn % 24 == 0 ) {
				stmtUpdate.execute( "UPDATE users " +
						"SET rating_points = ( rating_points + 1 )" );
				
				// Remove old chat messages every 24 turns
				long oldTimestamp = ( long ) ( System.currentTimeMillis() * 0.001 ) - 2419200;
				
				stmtUpdate.execute( "DELETE FROM chat " +
						"WHERE timestamp < " + oldTimestamp );
				
				// Check if anyone should receive a medal for unit counts
				long tmpTimestamp = ( long ) ( System.currentTimeMillis() * 0.001 );
				
				rs = stmt.executeQuery( "SELECT user_id " +
						"FROM ruler " +
						"WHERE ( infantry + " +
							"( SELECT SUM(infantry) FROM army WHERE army.ruler_id = ruler.ruler_id ) + " +
							"( SELECT SUM( infantry ) FROM transfer WHERE transfer.ruler_id = ruler.ruler_id ) ) > 4000000 " );
				while( rs.next() ) {
					int user_id = rs.getInt( "user_id" );
					rs2 = stmt2.executeQuery( "SELECT count(*) " +
							"FROM medals " +
							"WHERE title LIKE 'Infantry branch insignia' AND user_id = " + user_id );
					
					if( rs2.next() && rs2.getInt( 1 ) == 0 ) {
						stmtUpdate.execute( "INSERT INTO medals " +
								"( title, value, user_id, timestamp ) " +
								"VALUES( 'Infantry branch insignia', 2, " + user_id + ", " + tmpTimestamp + " )" );
					}
				}

				rs = stmt.executeQuery( "SELECT user_id " +
						"FROM ruler " +
						"WHERE ( cavalry + " +
							"( SELECT SUM(cavalry) FROM army WHERE army.ruler_id = ruler.ruler_id ) + " +
							"( SELECT SUM( cavalry ) FROM transfer WHERE transfer.ruler_id = ruler.ruler_id ) ) > 400000 " );
				while( rs.next() ) {
					int user_id = rs.getInt( "user_id" );
					rs2 = stmt2.executeQuery( "SELECT count(*) " +
							"FROM medals " +
							"WHERE title LIKE 'Cavalry branch insignia' AND user_id = " + user_id );
					
					if( rs2.next() && rs2.getInt( 1 ) == 0 ) {
						stmtUpdate.execute( "INSERT INTO medals " +
								"( title, value, user_id, timestamp ) " +
								"VALUES( 'Cavalry branch insignia', 2, " + user_id + ", " + tmpTimestamp + " )" );
					}
				}
				
				rs = stmt.executeQuery( "SELECT user_id " +
						"FROM ruler " +
						"WHERE ( artillery + " +
							"( SELECT SUM(artillery) FROM army WHERE army.ruler_id = ruler.ruler_id ) + " +
							"( SELECT SUM( artillery ) FROM transfer WHERE transfer.ruler_id = ruler.ruler_id ) ) > 400000 " );
				while( rs.next() ) {
					int user_id = rs.getInt( "user_id" );
					rs2 = stmt2.executeQuery( "SELECT count(*) " +
							"FROM medals " +
							"WHERE title LIKE 'Artillery branch insignia' AND user_id = " + user_id );
					
					if( rs2.next() && rs2.getInt( 1 ) == 0 ) {
						stmtUpdate.execute( "INSERT INTO medals " +
								"( title, value, user_id, timestamp ) " +
								"VALUES( 'Artillery branch insignia', 2, " + user_id + ", " + tmpTimestamp + " )" );
					}
				}
			}

			if( turn == 2 ) {
				// The first turn update we inform players of the start through a news item
				newsItem.clear();
				newsItem.addTitleText( "The game has begun", true );
				newsItem.addText( "The first turn is being updated.", true );
				newsItem.addText( "\n", false );
				newsItem.addText( "This means game days are now going to pass until this round ends.", true );
				newsItem.addText( "\n\n", false );
				newsItem.addText( "Good luck and have fun!", true );

				for( int i = 0; i < total; i ++ ) {
					newsItem.insert( rulers[i], 2, turn, date );
				}
			}
			
			// remove all old messages
			rs = stmt.executeQuery( "SELECT remove_news, turns_inactive FROM game" );
			rs.next();
			int remove_news = rs.getInt( "remove_news" ); 
			int inactiveTurn = rs.getInt( "turns_inactive" ); 
			stmt.executeUpdate( "DELETE FROM news WHERE turn < " + ( turn - remove_news ) );
			
			if( turn % 24 == 5 ) {
				// Remove villages and armies from inactive players from the game
				rs2 = stmt2.executeQuery( "SELECT ruler_id " +
						"FROM ruler " +
						"WHERE active_turn < " + ( turn - ( inactiveTurn * 2 ) ) );
				while( rs2.next() ) {
					stmtUpdate.execute( "DELETE FROM army " +
							"WHERE ruler_id = " + rs2.getInt( 1 ) );
					stmtUpdate.execute( "UPDATE village " +
							"SET ruler_id = -1, loyal_to = -1 " +
							"WHERE ruler_id = " + rs2.getInt( 1 ) );
				}
			}
			
			rs = stmt.executeQuery( "SELECT * FROM messages WHERE turn < " + ( turn - remove_news ) );
			while ( rs.next() ) {
				int message_id = rs.getInt( "message_id" );
				stmtUpdate.execute( "UPDATE messages SET parent = -1 WHERE parent = " + message_id );
				stmtUpdate.execute( "DELETE FROM messages WHERE message_id = " + message_id );
				stmtUpdate.execute( "DELETE FROM message_ruler WHERE message_id = " + message_id );
			}
			//stmt.executeUpdate( "DELETE FROM news WHERE turn < " + ( turn - remove_news ) );
			
			stmt.executeUpdate( "DELETE FROM ruler_expedition WHERE completed = 1 AND complete_turn < " + ( turn - remove_news ) );
			
			// remove old trades
			stmt.executeUpdate( "DELETE FROM trade WHERE NOT complete_turn = 0 AND complete_turn < " + ( turn - remove_news ) );
			
			// Subtract 1 turn from premium accounts except during special event
			if( special_event_started == 0 ) {
				stmt.executeUpdate( "UPDATE users SET premium = ( premium - 1 ) WHERE premium > -1" );
				lowOnPremiumWarning();
			}
			con.commit();
			
			try {
				sendNewsEmails();
			} catch ( SendFailedException sendFailedException ) {
				AgesOfStrifeServer.log.debug( "Failed to send an e-mail to one or more addresses." );
			} catch ( MessagingException messagingException ) {
				AgesOfStrifeServer.log.debug( "Error sending e-mails." );
			}
			con.commit();
			

		} catch ( Exception e ) {
			AgesOfStrifeServer.log.error( getStackError( e ) );
			e.printStackTrace();
		}
		finally {
			timestamp = System.currentTimeMillis() - timestamp;
			AgesOfStrifeServer.log.info( "Turn: " + turn + ", updated in " + timestamp + " ms." );
			try {
				stmtUpdate.execute( "UPDATE game " +
						"SET update_time = " + timestamp + ", turn = " + turn + ", date = '" + date + "', turn_update = 0, season = " + season );
				AgesOfStrifeServer.log.debug( "Closing connection with DB." );
				con.close();
			}
			catch( SQLException sqlException ) {
				AgesOfStrifeServer.log.error( "There was a problem storing the update settings and closing the database connection." );
			}
		}
	}
	
	private void updateLoyalty() throws SQLException, NoSuchAlgorithmException {
		rs = stmt.executeQuery( "SELECT * " +
				"FROM village " +
				"WHERE ruler_id != -1 AND NOT ( loyalty = 100 AND ruler_id = loyal_to )" );
		while( rs.next() ) {
			float loyalty = rs.getFloat( "loyalty" );
			int loyal_to = rs.getInt( "loyal_to" );
			int ruler_id = rs.getInt( "ruler_id" );
			int hide = rs.getInt( "hide" );
			String name = rs.getString( "name" );
			String secondName = rs.getString( "second_name" );
			int x = rs.getInt( "x" );
			int y = rs.getInt( "y" );
			if( loyal_to == -1 ) {
				loyal_to = ruler_id;
			}
			
			if( ruler_id == loyal_to ) { 
				loyalty ++;
				if( loyalty > 100 ) {
					loyalty = 100;
				}
			}
			else {
				loyalty --;
				if( loyalty < 50 ) {
					loyal_to = ruler_id;
					loyalty = 50;
					newsItem.clear(); 
					newsItem.addTitleText( name, false );
					newsItem.addTitleText( " ", false );
					newsItem.addTitleText( "is now loyal to us", true );
					
					newsItem.addText( "The populations loyalty has increased to 50% loyal towards us.", true );
					
					newsItem.insert( ruler_id, 2, turn, date );
				}
				else {
					rs2 = stmt2.executeQuery( "SELECT faction_id " +
							"FROM faction_member " +
							"WHERE ruler_id = " + ruler_id + " AND invited = 0 AND requested = 0" );
					int faction_id = -1;
					if( rs2.next() ) {
						faction_id = rs2.getInt( "faction_id" );
						rs2 = stmt2.executeQuery( "SELECT * " +
								"FROM army " +
								"WHERE travel = 0 AND x = " + x + " AND y = " + y + " " +
									"AND ruler_id IN (SELECT ruler_id FROM faction_member WHERE invited = 0 AND requested = 0 AND faction_id = " + faction_id + " )" );
					}
					else {
						rs2 = stmt2.executeQuery( "SELECT * " +
								"FROM army " +
								"WHERE travel = 0 AND x = " + x + " AND y = " + y + " " +
									"AND ruler_id = " + ruler_id );
					}
					boolean done = false;
					int resistance = ( int ) Math.round( rs.getInt( "population" ) * 0.01 * loyalty );
					
					while( rs2.next() && !done ) {
						long defense = rs2.getInt( "scout" ) * 4l + rs2.getInt( "infantry" ) * 6l + rs2.getInt( "cavalry" ) * 30l + rs2.getInt( "artillery" ) * 48l;
						if( defense > resistance ) {
							done = true;
						}
					}
					
					if( !done ) {
						newsItem.clear();
						newsItem.addTitleText( name, false );
						newsItem.addTitleText( " ", false );
						newsItem.addTitleText( "has rebelled and is no longer under our control", true );
						
						newsItem.addText( "We were not able to keep the population subdued.", true );
						newsItem.addText( "\n\n", false );
						newsItem.addText( "They have returned control to their former ruler.", true );
						
						newsItem.insert( ruler_id, 2, turn, date );

						newsItem.clear();
						
						newsItem.addTitleText( name + " ", false );
						newsItem.addTitleText( "has rebelled and joined us", true );
						
						newsItem.addText( "Occupation forces were not strong enough to subdue the population.", true );
						newsItem.addText( "\n\n", false );
						newsItem.addText( "The population has returned control of the village to us.", true );
						if( secondName != null && secondName != "" ) {
							newsItem.addText( "The village name has been changed back to " + secondName + ".", true );
							name = secondName;
						}
						
						newsItem.insert( loyal_to, 2, turn, date );
						ruler_id = loyal_to;
						hide = 0;
					}
				}
			}
			
			stmtUpdate.execute( "UPDATE village " +
					"SET loyalty = " + loyalty + ", loyal_to = " + loyal_to + ", ruler_id = " + ruler_id + "," +
							"hide = " + hide + ", name = '" + name + "' " +
					"WHERE village_id = " + rs.getInt( "village_id" ) );
		}
	}

	private void conquerVillagesByIndependentArmies() throws SQLException, NoSuchAlgorithmException {
		rs = stmt.executeQuery( "SELECT * " +
				"FROM army " +
				"WHERE ruler_id = -1" );
		while( rs.next() ) {
			int army_id = rs.getInt( "army_id" );
			String armyName = rs.getString( "name" );
			double x = rs.getDouble( "actual_x" );
			double y = rs.getDouble( "actual_y" );
			int scout = rs.getInt( "scout" );
			int infantry = rs.getInt( "infantry" );
			int cavalry = rs.getInt( "cavalry" );
			int artillery = rs.getInt( "artillery" );
			int attack = scout * 2 + infantry * 3 + cavalry * 15 + artillery * 24;
			
			rs2 = stmt2.executeQuery( "SELECT * " +
					"FROM village " +
					"WHERE ruler_id != -1 AND x < " + ( x + 3 ) + " AND x > " + ( x - 3 ) + "AND y < " + ( y + 3 ) + " AND y > " + ( y - 3 ) + " AND " +
							"( SELECT count(*) FROM army WHERE army.x = village.x AND army.y = village.y AND travel = 0 AND ruler_id != -1 AND scout + infantry + cavalry + artillery > 100 ) = 0" );
			while( rs2.next() ) {
				int village_id = rs2.getInt( "village_id" );
				int village_ruler_id = rs2.getInt( "ruler_id" );
				int villageX = rs2.getInt( "x" );
				int villageY = rs2.getInt( "y" );
				String name = rs2.getString( "name" );
				int totalPopulation = rs2.getInt( "population" );
				int population = ( int ) ( rs2.getInt( "population" ) * 0.5 );
				int populationAfter = population - attack;
				if( populationAfter < 0 ) {
					populationAfter = 0;
				}
				
				int scoutBefore = scout;
				int infantryBefore = infantry;
				int cavalryBefore = cavalry;
				int artilleryBefore = artillery;
				
				scout -= ( int ) ( population * 0.3 );
				int add = 0;
				if( scout < 0 ) {
					add = -scout;
					scout = 0;
				}
				infantry -= ( int ) ( ( add + population ) * 0.2 );
				if( infantry < 0 ) {
					add = -infantry;
					infantry = 0;
				}
				cavalry -= ( int ) ( ( add + population ) * 0.05 );
				if( cavalry < 0 ) {
					add = -cavalry;
					cavalry = 0;
				}
				artillery -= ( int ) ( ( add + population ) * 0.05 );
				if( artillery < 0 ) {
					if( scout > 0 ) {
						scout -= artillery;
						if( scout < 0 ) {
							scout = 0;
						}
					}
					artillery = 0;
				}
				newsItem.clear();
				
				if( populationAfter == 0 ) {
					// Independents took the village
					newsItem.addTitleText( "An independent army took", true );
					newsItem.addTitleText( " " + name, false );
					
					newsItem.addText( "We lost", true );
					newsItem.addText( " " + name + " ", false );
					newsItem.addText( "at", true );
					newsItem.addText( " <a href=\"../operations/map.php?x=" + ( villageX - 20 ) + "&y=" + ( villageY - 20 ) + "\">(" + villageX + ", " + villageY + ")</a>\n\n", false );
					
					stmtUpdate.execute( "UPDATE village " +
							"SET ruler_id = -1, start_place = 0, population = " + ( totalPopulation - ( population - populationAfter ) ) + ", " +
									"loyal_to = -1 " +
							"WHERE village_id = " + village_id );
				}
				else {
					// Independents couldn't take the village
					newsItem.addTitleText( "An independent army tried to take", true );
					newsItem.addTitleText( " " + name, false );
					
					newsItem.addText( "Our population at", true );
					newsItem.addText( " " + name + " ", false );
					newsItem.addText( "managed to fight off an independent army, see", true );
					newsItem.addText( " <a href=\"../operations/map.php?x=" + ( villageX - 20 ) + "&y=" + ( villageY - 20 ) + "\">(" + villageX + ", " + villageY + ")</a>\n\n", false );

					stmtUpdate.execute( "UPDATE village " +
							"SET population = " + ( totalPopulation - ( population - populationAfter ) ) + " " +
							"WHERE village_id = " + village_id );
				}
				
				newsItem.addText( armyName + " ", false );
				newsItem.addText( "of independent forces", true );
				newsItem.addText( "\n", false );
				newsItem.addText( "Scouts before", true );
				newsItem.addText( ": " + Utils.formatNumber( "" + scoutBefore ) + "\n", false );
				newsItem.addText( "Scouts after", true );
				newsItem.addText( ": " + Utils.formatNumber( "" + scout ) + "\n", false );
				newsItem.addText( "Infantry before", true );
				newsItem.addText( ": " + Utils.formatNumber( "" + infantryBefore ) + "\n", false );
				newsItem.addText( "Infantry after", true );
				newsItem.addText( ": " + Utils.formatNumber( "" + infantry ) + "\n", false );
				newsItem.addText( "Cavalry before", true );
				newsItem.addText( ": " + Utils.formatNumber( "" + cavalryBefore ) + "\n", false );
				newsItem.addText( "Cavalry after", true );
				newsItem.addText( ": " + Utils.formatNumber( "" + cavalry ) + "\n", false );
				newsItem.addText( "Artillery before", true );
				newsItem.addText( ": " + Utils.formatNumber( "" + artilleryBefore ) + "\n", false );
				newsItem.addText( "Artillery after", true );
				newsItem.addText( ": " + Utils.formatNumber( "" + artillery ) + "\n\n", false );
				
				newsItem.addText( "Resistance at", true );
				newsItem.addText( " " + name + "\n", false );
				newsItem.addText( "Opposing villagers before", true );
				newsItem.addText( ": " + Utils.formatNumber( "" + ( int ) ( population ) ) + "\n", false );
				newsItem.addText( "Opposing villagers after", true );
				newsItem.addText( ": " + Utils.formatNumber( "" + ( int ) ( populationAfter ) ) + "\n", false );
				
				newsItem.insert( village_ruler_id, 2, turn, date );
			}
			
			stmtUpdate.execute( "UPDATE army " +
					"SET scout = " + scout + ", infantry = " + infantry + ", cavalry = " + cavalry + ", artillery = " + artillery + " " +
					"WHERE army_id = " + army_id );
			con.commit();
		}
	}
	
	private void updateIdleIndependentArmies() throws SQLException {
		rs = stmt.executeQuery( "SELECT * " +
				"FROM army " +
				"WHERE ruler_id = -1 AND ( SELECT count(*) FROM army_orders WHERE army_orders.army_id = army.army_id ) = 0 AND " +
				"arrived_turn < " + ( turn - 3 ) );
		
		rs2 = stmt2.executeQuery( "SELECT max(x), max(y) " +
				"FROM village" );
		rs2.next();
		int maxX = rs2.getInt( 1 );
		int maxY = rs2.getInt( 2 );

		rs2 = stmt2.executeQuery( "SELECT global_orders " +
				"FROM game" );
		rs2.next();
		int global_orders = rs2.getInt( 1 );

		while( rs.next() ) {
			int army_id = rs.getInt( "army_id" );
			int x = rs.getInt( "x" );
			int y = rs.getInt( "y" );
			boolean addOrder = false;
			
			if( global_orders == 0 ) {
				// Move south yall
				if( y < maxY ) {
					y += 3;
					if( y > maxY ) {
						y = maxY;
					}
					addOrder = true;
				}
			}
			else if( global_orders == 1 ) {
				// Move to the east
				if( x < maxX ) {
					x += 3;
					if( x > maxX ) {
						x = maxX;
					}
					addOrder = true;
				}
			}
			else if( global_orders == 2 ) {
				// Move north
				if( y > 0 ) {
					y -= 3;
					if( y < 0 ) {
						y = 0;
					}
					addOrder = true;
				}
			}
			else if( global_orders == 3 ) {
				// Go west
				if( x > 0 ) {
					x -= 3;
					if( x < 0 ) {
						x = 0;
					}
					addOrder = true;
				}
			}
			else if( global_orders == 4 ) {
				// Center, is where it is at
				int targetX = ( int ) ( maxX * 0.5 );
				int targetY = ( int ) ( maxY * 0.5 );
				if( x < targetX ) {
					x += 2;
					if( x > targetX ) {
						x = targetX;
					}
					addOrder = true;
				}
				else if( x > targetX ) {
					x -= 2;
					if( x < targetX ) {
						x = targetX;
					}
					addOrder = true;
				}
				
				if( y > targetY ) {
					y -= 2;
					if( y < targetY ) {
						y = targetY;
					}
					addOrder = true;
				}
				else if( y < targetY ) {
					y += 2;
					if( y > targetY ) {
						y = targetY;
					}
					addOrder = true;
				}
			}			
			else if( global_orders == 5 ) {
				// Randomly move around
				if( Math.random() > 0.5 ) {
					x += 2;
				}
				else {
					x -= 2;
				}
				if( Math.random() > 0.5 ) {
					y += 2;
				}
				else {
					y -= 2;
				}
				
				if( x > maxX ) {
					x = maxX;
				}
				else if( x < 0 ) {
					x = 0;
				}
				
				if( y > maxY ) {
					y = maxY;
				}
				else if( y < 0 ) {
					y = 0;
				}
				addOrder = true;
			}
			if( addOrder ) {
				stmtUpdate.execute( "INSERT INTO army_orders " +
						"( army_id, order_type, order_value, order_value2 ) " +
						"VALUES( " + army_id + ", 1, " + x + ", " + y + " )" );
			}
		}
	}

	private void updateFactionColors() throws SQLException {
		AgesOfStrifeServer.log.debug( "Updating faction colors." );
		// Let's determine how many colors we have
		rs = stmt.executeQuery( "SELECT count(*) " +
				"FROM faction_colors" );
		rs.next();
		int totalColors = rs.getInt( 1 );
		
		rs = stmt.executeQuery( "SELECT color_id " +
				"FROM faction_colors " +
				"WHERE ( SELECT count(*) FROM faction WHERE faction.faction_id = faction_colors.faction_id ) = 0" );
		while ( rs.next() ) {
			int color_id = rs.getInt( "color_id" );
			stmtUpdate.execute( "UPDATE faction_colors " +
					"SET faction_id = -1 " +
					"WHERE color_id = " + color_id );
		}
		
		// Now lets see below what score a faction should not have a color anymore
		rs = stmt.executeQuery( "SELECT score " +
			"FROM faction " +
			"ORDER BY score DESC " +
			"LIMIT " + ( totalColors - 1 ) + ", 1" );
		// If there is any faction with a color
		if( rs.next() ) {
			long minScore = rs.getLong( "score" );
			// Let's remove the color from those factions
			rs = stmt.executeQuery( "SELECT faction.faction_id " +
					"FROM faction " +
					"JOIN faction_colors ON faction.faction_id = faction_colors.faction_id " +
					"WHERE score < " + minScore );
			while ( rs.next() ) {
				int faction_id = rs.getInt( "faction_id" );
				stmtUpdate.execute( "UPDATE faction_colors " +
						"SET faction_id = -1 " +
						"WHERE faction_id = " + faction_id );
			}
		}
		
		con.commit();
		
		// Above what score does a faction need to have a color
		rs = stmt.executeQuery( "SELECT score " +
				"FROM faction " +
				"ORDER BY score DESC " +
				"LIMIT " + ( totalColors - 3 ) + ", 1" );
		long maxScore = 0;
		if( rs.next() ) {
			maxScore = rs.getLong( "score" );
		}
		
		// Let's assign colors to the top factions without one
		rs = stmt.executeQuery( "SELECT faction_id " +
				"FROM faction " +
				"WHERE score > " + maxScore + " " +
				"ORDER BY score DESC" );
		while ( rs.next() ) {
			int faction_id = rs.getInt( "faction_id" );
			rs2 = stmt2.executeQuery( "SELECT count(*) " +
					"FROM faction_colors " +
					"WHERE faction_id = " + faction_id );
			rs2.next();
			if( rs2.getInt( 1 ) == 0 ) {
				rs2 = stmt2.executeQuery( "SELECT color_id " +
						"FROM faction_colors " +
						"WHERE faction_id = -1 " +
						"ORDER BY RAND()" );
				rs2.next();
				int color_id = rs2.getInt( "color_id" );
				stmtUpdate.execute( "UPDATE faction_colors " +
						"SET faction_id = " + faction_id + " " +
						"WHERE color_id = " + color_id );
			}
		}
	}

	private void handleArmyInstructions() throws SQLException {
		int min_x = -1;
		int max_x = -1;
		int min_y = -1;
		int max_y = -1;
		rs = stmt.executeQuery( "SELECT MAX(x), MAX(y) " +
				"FROM village" );
		if( rs.next() ) {
			max_x = rs.getInt( 1 );
			max_y = rs.getInt( 2 );
		}
		
		rs = stmt.executeQuery( "SELECT * " +
				"FROM army " +
				"WHERE officer_id != -1 AND instructions != 0 AND training = 0 AND mission = 0 " +
					"AND fortified = 0 AND follow = -1 AND scout + infantry + cavalry + artillery > 0 " +
					"AND ( SELECT count(*) FROM army_orders WHERE army_orders.army_id = army.army_id ) = 0" );
		while ( rs.next() ) {
			int army_id = rs.getInt( "army_id" );
			int ruler_id = rs.getInt( "ruler_id" );
			int x = rs.getInt( "x" );
			int y = rs.getInt( "y" );
			int instructions = rs.getInt( "instructions" );
			rs2 = stmt2.executeQuery( "SELECT faction_id " +
					"FROM faction_member " +
					"WHERE ruler_id = " + ruler_id + " AND invited = 0 AND requested = 0" );
			int faction_id = -1;
			if( rs2.next() ) {
				faction_id = rs2.getInt( "faction_id" );
			}
			
			long ownScore = rs.getLong( "scout" ) * 32 + rs.getLong( "infantry" ) * 48 + rs.getLong( "cavalry" ) * 256 + rs.getLong( "artillery" ) * 400;
			long enemyScore = 0;
			
			if( faction_id == -1 ) {
				rs2 = stmt2.executeQuery( "SELECT SUM(scout), SUM(infantry), SUM(cavalry), SUM(artillery) " +
						"FROM army " +
						"WHERE ruler_id = " + ruler_id + " AND army_id != " + army_id + " AND " + x + " + 3 >= actual_x AND " + x + " - 3 <= actual_x AND  " + y + " + 3 >= actual_y AND " + y + " - 3 <= actual_y" );
				if( rs2.next() ) {
					ownScore += rs2.getLong( 1 ) * 32 + rs2.getLong( 2 ) * 48 +  rs2.getLong( 3 ) * 256 + rs2.getLong( 4 ) * 400;
				}
				
				rs2 = stmt2.executeQuery( "SELECT SUM(scout), SUM(infantry), SUM(cavalry), SUM(artillery) " +
						"FROM army " +
						"WHERE ruler_id != " + ruler_id + " AND " + x + " + 3 >= actual_x AND " + x + " - 3 <= actual_x AND  " + y + " + 3 >= actual_y AND " + y + " - 3 <= actual_y" );
				if( rs2.next() ) {
					enemyScore += rs2.getLong( 1 ) * 32 + rs2.getLong( 2 ) * 48 +  rs2.getLong( 3 ) * 256 + rs2.getLong( 4 ) * 400;
				}
			}
			else {
				rs2 = stmt2.executeQuery( "SELECT SUM(scout), SUM(infantry), SUM(cavalry), SUM(artillery) " +
						"FROM army " +
						"JOIN faction_member ON army.ruler_id = faction_member.ruler_id " +
						"WHERE faction_id = " + faction_id + " AND requested = 0 AND invited = 0 " +
								"AND army_id != " + army_id + " AND " + x + " + 3 >= actual_x AND " + x + " - 3 <= actual_x AND  " + y + " + 3 >= actual_y AND " + y + " - 3 <= actual_y" );
				if( rs2.next() ) {
					ownScore += rs2.getLong( 1 ) * 32l + rs2.getLong( 2 ) * 48l +  rs2.getLong( 3 ) * 256l + rs2.getLong( 4 ) * 400l;
				}
				
				rs2 = stmt2.executeQuery( "SELECT SUM(scout), SUM(infantry), SUM(cavalry), SUM(artillery) " +
						"FROM army " +
						"WHERE ruler_id NOT IN ( SELECT ruler_id FROM faction_member WHERE faction_id = " + faction_id + " AND requested = 0 AND invited = 0 ) AND army_id != " + army_id + " AND " + x + " + 3 >= actual_x AND " + x + " - 3 <= actual_x AND  " + y + " + 3 >= actual_y AND " + y + " - 3 <= actual_y" );
				if( rs2.next() ) {
					enemyScore += rs2.getLong( 1 ) * 32l + rs2.getLong( 2 ) * 48l +  rs2.getLong( 3 ) * 256l + rs2.getLong( 4 ) * 400l;
				}
			}
			
			// There are enemies close by
			if( enemyScore > 0 ) {
				AgesOfStrifeServer.log.debug( "Enemies are close by for army with id: " + army_id + ", our faction id: " + faction_id );
				double enemy_x = -1;
				double enemy_y = -1;
				int enemy_army_id = -1;
				int enemy_travel = 0;
				
				if( faction_id == -1 ) {
					rs2 = stmt2.executeQuery( "SELECT actual_x, actual_y, army_id, travel " +
							"FROM army " +
							"WHERE ruler_id != " + ruler_id + " AND " + x + " + 3 >= actual_x AND " + x + " - 3 <= actual_x AND  " + y + " + 3 >= actual_y AND " + y + " - 3 <= actual_y " +
							"ORDER BY ( scout * 32 + infantry * 48 + cavalry * 256 + artillery * 400 ) DESC " +
							"LIMIT 1" );
					if( rs2.next() ) {
						enemy_x = rs2.getDouble( "actual_x" );
						enemy_y = rs2.getDouble( "actual_y" );
						enemy_army_id = rs2.getInt( "army_id" );
						enemy_travel = rs2.getInt( "travel" );
					}
				}
				else {
					rs2 = stmt2.executeQuery( "SELECT actual_x, actual_y, army_id, travel " +
							"FROM army " +
							"WHERE ruler_id NOT IN ( SELECT ruler_id FROM faction_member WHERE faction_id = " + faction_id + " AND requested = 0 AND invited = 0 ) AND army_id != " + army_id + " AND " + x + " + 3 >= actual_x AND " + x + " - 3 <= actual_x AND  " + y + " + 3 >= actual_y AND " + y + " - 3 <= actual_y " +
							"ORDER BY ( scout * 32 + infantry * 48 + cavalry * 256 + artillery * 400 ) DESC " +
							"LIMIT 1" );
					if( rs2.next() ) {
						enemy_x = rs2.getDouble( "actual_x" );
						enemy_y = rs2.getDouble( "actual_y" );
						enemy_army_id = rs2.getInt( "army_id" );
						enemy_travel = rs2.getInt( "travel" );
					}
				}
				
				if( enemy_x != -1 && enemy_y != -1 ) {
					long difference = ( long ) ( ( enemyScore + ownScore ) * 0.04 );
//					AgesOfStrifeServer.log.debug( "Own score: " + ownScore );
//					AgesOfStrifeServer.log.debug( "Enemy score: " + enemyScore );
//					AgesOfStrifeServer.log.debug( "Difference: " + difference );
					
					// enemies are stronger, lets run
					if( ruler_id != -1 && enemyScore - difference > ownScore ) {
						int target_x = x + ( x - ( int ) Math.round( enemy_x ) );
						int target_y = y + ( y - ( int ) Math.round( enemy_y ) );
						
						if( target_x > min_x && target_x <= max_x && target_y > min_y && target_y <= max_y && !( target_x == x && target_y == y ) ) { 
							stmtUpdate.execute( "INSERT INTO army_orders " +
									"( army_id, order_type, order_value, order_value2, rank ) " +
									"VALUES( " + army_id + ", 1, " + target_x + ", " + target_y + ", 0 )" );
							rs2 = stmt2.executeQuery( "SELECT army_id " +
									"FROM army " +
									"WHERE follow = " + army_id );
							while( rs2.next() ) {
								stmtUpdate.execute( "INSERT INTO army_orders " +
										"( army_id, order_type, order_value, order_value2, rank ) " +
										"VALUES( " + rs2.getInt( "army_id" ) + ", 1, " + target_x + ", " + target_y + ", 0 )" );
							}
							AgesOfStrifeServer.log.debug( "Retreat orders queued for army with id: " + army_id );
						}
					}
					// we are set to aggressive and enemies are weaker, lets try and attack
					else if( ruler_id == -1 || ( instructions == 2 && enemyScore + difference < ownScore ) ) {
						int target_x = -1;
						int target_y = -1;
						
						if( enemy_travel == 1 ) {
							rs2 = stmt2.executeQuery( "SELECT order_value, order_value2, complete_turn " +
									"FROM army_orders " +
									"WHERE army_id = " + enemy_army_id + " AND rank = 0" );
							
							if( rs2.next() ) {
								int destination_x = rs2.getInt( "order_value" );
								int destination_y = rs2.getInt( "order_value2" );
								
								int time = turn - rs2.getInt( "complete_turn" );
								
								double total = time + 1;
								double part = 1.0 / total;
							
								target_x = ( int ) Math.round( enemy_x + ( destination_x - enemy_x ) * part );
								target_y = ( int ) Math.round( enemy_y + ( destination_y - enemy_y ) * part );
							}
						}
						else {
							target_x = ( int ) Math.round( enemy_x );
							target_y = ( int ) Math.round( enemy_y );
						}

						if( target_x > min_x && target_x <= max_x && target_y > min_y && target_y <= max_y && 
								target_x != x && target_y != y ) { 
							stmtUpdate.execute( "INSERT INTO army_orders " +
									"( army_id, order_type, order_value, order_value2, rank ) " +
									"VALUES( " + army_id + ", 1, " + target_x + ", " + target_y + ", 0 )" );
							rs2 = stmt2.executeQuery( "SELECT army_id " +
									"FROM army " +
									"WHERE follow = " + army_id );
							while( rs2.next() ) {
								stmtUpdate.execute( "INSERT INTO army_orders " +
										"( army_id, order_type, order_value, order_value2, rank ) " +
										"VALUES( " + rs2.getInt( "army_id" ) + ", 1, " + enemy_x + ", " + enemy_y + ", 0 )" );
							}
							AgesOfStrifeServer.log.debug( "Attack orders queued for army with id: " + army_id );
						}
						else {
							AgesOfStrifeServer.log.warn( "We can't move the army because it will be out of the game map area!" );
						}
					}
				}
				else {
					AgesOfStrifeServer.log.warn( "For some reason we can't find the enemies location, even though we found at least one in range!" );
				}
			}
		}
	}

	private void updateCapitalChanges() throws SQLException, NoSuchAlgorithmException {
		rs = stmt.executeQuery( "SELECT ruler_id, village_id, name " +
				"FROM village " +
				"WHERE become_capital != -1 AND become_capital <= " + turn );
		while ( rs.next() ) {
			int ruler_id = rs.getInt( "ruler_id" );
			int village_id = rs.getInt( "village_id" );
			String name = rs.getString( "name" );
			rs2 = stmt2.executeQuery( "SELECT village_id, add_turn " +
					"FROM village " +
					"WHERE start_place = 1 AND ruler_id = " + ruler_id );
			
			int add_turn;
			if( rs2.next() ) {
				int old_capital_id = rs2.getInt( "village_id" );
				add_turn = rs2.getInt( "add_turn" );
				stmtUpdate.execute( "UPDATE village " +
						"SET start_place = 0 " +
						"WHERE village_id = " + old_capital_id );
			}
			else {
				add_turn = 0;
			}
			stmtUpdate.execute( "UPDATE village " +
					"SET start_place = 1, add_turn = " + add_turn + ", become_capital = -1 " +
					"WHERE village_id = " + village_id );
			
			newsItem.clear();
			
			newsItem.addTitleText( name + " ", false );
			newsItem.addTitleText( "has become our capital", true );
			
			newsItem.addText( "Our administration has been moved to a new location.", true );
			newsItem.addText( "\n" + name + " ", false );
			newsItem.addText( "has now become the center of our empire,", true );
			newsItem.addText( "\n", false );
			newsItem.addText( "our reach is now determined from the new capital.", true );
			newsItem.addText( "\n\n", false );
			newsItem.addText( "We should make sure", true );
			newsItem.addText( " " + name + " ", false );
			newsItem.addText( "is protected from any enemies.", true );
			
			newsItem.insert( ruler_id, 2, turn, date ); 
		}
	}

	private void updateMilitaryMorale( int turns_inactive ) throws SQLException, NoSuchAlgorithmException {
		// First handle the soldiers payments
		rs = stmt.executeQuery( "SELECT gold, ruler_id " +
				"FROM ruler " +
				"WHERE payday = 1" );
		while ( rs.next() ) {
			int ruler_id = rs.getInt( "ruler_id" );
			int gold = rs.getInt( "gold" );
			rs2 = stmt2.executeQuery( "SELECT SUM( scout + infantry + cavalry + artillery ) " +
		    		"FROM army " +
		    		"WHERE ruler_id = " + ruler_id );
			long totalArmy = 0;
			if( rs2.next() ) {
				totalArmy += rs2.getLong( 1 );
			}
			/*rs2 = stmt2.executeQuery( "SELECT SUM( scouts + infantry + cavalry + artillery ) " +
		    		"FROM transfer " +
		    		"WHERE ruler_id = " + ruler_id );
			if( rs2.next() ) {
				totalArmy += rs2.getLong( 1 );
			}*/
			rs2 = stmt2.executeQuery( "SELECT ( recruits + scouts + infantry + cavalry + artillery ) " +
		    		"FROM ruler " +
		    		"WHERE ruler_id = " + ruler_id );
			if( rs2.next() ) {
				totalArmy += rs2.getLong( 1 );
			}
			int cost = ( int ) Math.round( totalArmy * 0.08 );
			// Check if the ruler has enough to pay
			if( gold >= cost ) {
				stmtUpdate.execute( "UPDATE ruler " +
						"SET gold = gold - " + cost + ", morale = morale + 0.4, payday = 0 " +
						"WHERE ruler_id = " + ruler_id );
				
				newsItem.clear();
				newsItem.addTitleText( "Soldiers have been paid", true );

				newsItem.addText( "All your soldiers received their payment.", true );
				newsItem.addText( "\n", false );
				newsItem.addText( "You have currently", true );
				newsItem.addText( " " + Utils.formatNumber( "" + totalArmy ) + " ", false );
				newsItem.addText( "men, paying them cost you: ", true );
				newsItem.addText( "<strong class=\"gold\">" + Utils.formatNumber( "" + cost ) + "</strong> ", false );
				newsItem.addText( "gold", true );
				newsItem.addText( ".\n", false );
				newsItem.addText( "Morale has significantly been improved!", true );
				
				newsItem.insert( ruler_id, 0, turn, date );
			}
		}
		
		// Deal with morale decline each 10 turns
		if( turn % 10 == 0 ) {
			AgesOfStrifeServer.log.debug( "Morale decline time" );
			rs = stmt.executeQuery( "SELECT last_battle, ruler_id " +
					"FROM ruler " +
					"WHERE resigned = 0 AND active_turn > " + ( turn - turns_inactive ) + " AND " +
							" ( ( SELECT SUM( scout + army.infantry + army.cavalry + army.artillery ) " +
					    		"FROM army " +
					    		"WHERE army.ruler_id = ruler.ruler_id ) + scouts + infantry + cavalry + artillery + recruits ) > 100000" );
			while( rs.next() ) {
				double decline = 0.004;
				int last_battle = rs.getInt( "last_battle" );
				int ruler_id = rs.getInt( "ruler_id" );
				last_battle = turn - last_battle;
				decline += ( Math.round( last_battle * 0.006 ) * 0.006 );
				stmtUpdate.execute( "UPDATE ruler " +
						"SET morale = morale - " + decline + 
						" WHERE ruler_id = " + ruler_id );
			}
		}
		
		// Clean up morale (above 1 = 1, below 0 = 0)
		stmtUpdate.execute( "UPDATE ruler " +
				"SET morale = 1 " +
				"WHERE morale > 1" );
		stmtUpdate.execute( "UPDATE ruler " +
				"SET morale = 0 " +
				"WHERE morale < 0" );
	}

	private void resolveBombardments() throws SQLException, NoSuchAlgorithmException {
		rs = stmt.executeQuery( "SELECT * " +
				"FROM army " +
				"JOIN officers ON officers.officer_id = army.officer_id " +
				"WHERE artillery > 0 AND bombard = 1 AND training = 0 AND travel = 0 " +
				"ORDER BY RAND()" );
		while ( rs.next() ) {
			AgesOfStrifeServer.log.debug( "Army ready to bombard, looking for target..." );
			int officer_id = rs.getInt( "officer_id" );
			String armyName = rs.getString( "name" );
			int ruler_id = rs.getInt( "ruler_id" );
			int officerOffenseBonus = rs.getInt( "offense" );
			rs2 = stmt2.executeQuery( "SELECT faction_id " +
					"FROM faction_member " +
					"WHERE requested = 0 AND invited = 0 AND ruler_id = " + ruler_id );
			int faction_id = -1;
			if( rs2.next() ) {
				faction_id = rs2.getInt( "faction_id" );
			}
			int artillery = rs.getInt( "artillery" );
			int x = rs.getInt( "x" );
			int y = rs.getInt( "y" );
			// Check if the army is not already in battle
			if( faction_id == -1 ) {
				rs2 = stmt2.executeQuery( "SELECT count( army_id ) " +
						"FROM army " +
						"WHERE actual_x + 0.5 >= " + x + " AND actual_x - 0.5 < " + x + " AND actual_y + 0.5 >= " + y + " AND actual_y - 0.5 < " + y + " " +
						" AND army.ruler_id != " + ruler_id  );
			}
			else {
				rs2 = stmt2.executeQuery( "SELECT count( army_id ) " +
						"FROM army " +
						"WHERE actual_x + 0.5 >= " + x + " AND actual_x - 0.5 < " + x + " AND actual_y + 0.5 >= " + y + " AND actual_y - 0.5 < " + y + " " +
							"AND army.ruler_id NOT IN ( SELECT ruler_id FROM faction_member WHERE faction_id = " + faction_id + " AND requested = 0 AND invited = 0 )" );
			}
			rs2.next();
			if( rs2.getInt( 1 ) == 0 ) { 
				// Only armies out of battle bombard
				if( faction_id == -1 ) {
					rs2 = stmt2.executeQuery( "SELECT * " +
							"FROM army " +
							"WHERE " + x + " >= actual_x - 3 AND " + x + " <= actual_x + 3 AND " +
							y + " >= actual_y - 3 AND " + y + " <= actual_y + 3 AND army.ruler_id != " + ruler_id + " AND " +
							"( scout > 0 OR infantry > 0 OR cavalry > 0 OR artillery > 0 ) " +
							"ORDER BY RAND() LIMIT 1" );
				}
				else {
					rs2 = stmt2.executeQuery( "SELECT * " +
							"FROM army " +
							"WHERE " + x + " >= actual_x - 3 AND " + x + " <= actual_x + 3 AND " +
							y + " >= actual_y - 3 AND " + y + " <= actual_y + 3 AND " +
							"( scout > 0 OR infantry > 0 OR cavalry > 0 OR artillery > 0 ) " +
							"AND army.ruler_id NOT IN ( SELECT ruler_id FROM faction_member WHERE faction_id = " + faction_id + " AND requested = 0 AND invited = 0 ) " +
							"ORDER BY RAND() LIMIT 1" );
				}
				
				if( rs2.next() ) {
					AgesOfStrifeServer.log.debug( "Bombarding!" );
					int army_id2 = rs2.getInt( "army_id" );
					int officer_id2 = rs2.getInt( "officer_id" );
					String armyName2 = rs2.getString( "name" );
					int ruler_id2 = rs2.getInt( "ruler_id" );
					int officerDefenseBonus = 0;
					if( officer_id2 != -1 ) {
						rs3 = stmt3.executeQuery( "SELECT defense " +
								"FROM officers " +
								"WHERE officer_id = " + officer_id );
						rs3.next();
						officerDefenseBonus = rs3.getInt( "defense" );
					}
						
					int scout2 = rs2.getInt( "scout" );
					int infantry2 = rs2.getInt( "infantry" );
					int cavalry2 = rs2.getInt( "cavalry" );
					int artillery2 = rs2.getInt( "artillery" );
					int travel = rs2.getInt( "travel" );
					int fortified2 = rs2.getInt( "fortified" );
					
					int scoutsLost = 0;
					int infantryLost = 0;
					int cavalryLost = 0;
					int artilleryLost = 0;

					int faction_id2 = -1;
					rs3 = stmt3.executeQuery( "SELECT faction_id " +
							"FROM faction_member " +
							"WHERE ruler_id = " + ruler_id2 + " AND requested = 0 AND invited = 0" );
					if( rs3.next() ) {
						faction_id2 = rs3.getInt( "faction_id" );
					}
					double bonus = 1.0;
					if( faction_id2 != -1 ) {
						rs3 = stmt3.executeQuery( "SELECT SUM( defense_bonus ) " +
								"FROM village_buildings " +
								"JOIN buildings ON buildings.building_id = village_buildings.building_id " +
								"JOIN village ON village.village_id = village_buildings.village_id " +
								"JOIN faction_member ON faction_member.ruler_id = village.ruler_id " +
								"WHERE x = " + ( int ) Math.round( rs2.getDouble( "actual_x" ) ) + " AND y = " + ( int ) Math.round( rs2.getDouble( "actual_y" ) ) + " AND faction_id = " + faction_id2 );
					}
					else {
						rs3 = stmt3.executeQuery( "SELECT SUM( defense_bonus ) " +
								"FROM village_buildings " +
								"JOIN buildings ON buildings.building_id = village_buildings.building_id " +
								"JOIN village ON village.village_id = village_buildings.village_id " +
								"WHERE x = " + ( int ) Math.round( rs2.getDouble( "actual_x" ) ) + " AND y = " + ( int ) Math.round( rs2.getDouble( "actual_y" ) ) + " AND ruler_id = " + ruler_id2 );
					}
					rs3.next();
					bonus -= rs3.getDouble( 1 );
					if( faction_id != -1 ) {
						rs3 = stmt3.executeQuery( "SELECT SUM( offense_bonus ) " +
								"FROM village_buildings " +
								"JOIN buildings ON buildings.building_id = village_buildings.building_id " +
								"JOIN village ON village.village_id = village_buildings.village_id " +
								"JOIN faction_member ON faction_member.ruler_id = village.ruler_id " +
								"WHERE x = " + x + " AND y = " + y + " AND faction_id = " + faction_id );
					}
					else {
						rs3 = stmt3.executeQuery( "SELECT SUM( offense_bonus ) " +
								"FROM village_buildings " +
								"JOIN buildings ON buildings.building_id = village_buildings.building_id " +
								"JOIN village ON village.village_id = village_buildings.village_id " +
								"WHERE x = " + x + " AND y = " + y + " AND ruler_id = " + ruler_id );
					}
					rs3.next();
					bonus += rs3.getDouble( 1 );
					bonus -= ( officerDefenseBonus * 0.02 );
					bonus += ( officerOffenseBonus * 0.02 );
					if( fortified2 == 1 ) {
						bonus -= 0.2;
					}
					
					if( bonus < 0 ) {
						bonus = 0;
					}
					
					// Calculate the attack points for the bombardment
					long attackPoints = ( int ) ( artillery * 1.6 * bonus );
					while( attackPoints > 0 && ( scout2 + infantry2 + cavalry2 + artillery2 != 0 ) ) {
						// While there are attack points left we divide them to target specific groups
						AgesOfStrifeServer.log.debug( "Attack points: " + attackPoints );
						int attackInf = ( int ) ( 0.4 * attackPoints );
						int attackScouts = ( int ) ( 0.04 * attackPoints );
						int attackCav = ( int ) ( 0.28 * attackPoints );;
						int attackArt = attackCav;
						if( scout2 < attackScouts ) {
							attackScouts -= scout2;
							scoutsLost += scout2;
							scout2 = 0;
							attackInf += attackScouts;
						}
						else {
							scoutsLost += attackScouts;
							scout2 -= attackScouts;
						}
						attackScouts = 0;
						
						if( infantry2 < attackInf * 0.25 ) {
							attackInf -= infantry2 * 4;
							infantryLost += infantry2;
							infantry2 = 0;
							attackArt += attackInf;
						}
						else {
							infantry2 -= ( int ) ( 0.25 * attackInf );
							infantryLost += ( int ) ( 0.25 * attackInf );
						}
						attackInf = 0;
						
						if( artillery2 * 25 < attackArt ) {
							attackArt -= artillery2 * 25;
							artilleryLost += artillery2;
							artillery2 = 0;
							attackCav += attackArt;
						}
						else {
							artillery2 -= ( int ) ( attackArt * 0.04 );
							artilleryLost += ( int ) ( attackArt * 0.04 );
						}
						attackArt = 0;
						
						if( cavalry2 * 25 < attackCav ) {
							attackCav -= cavalry2 * 25;
							cavalryLost += cavalry2;
							cavalry2 = 0;
						}
						else {
							cavalry2 -= ( int ) ( 0.04 * attackCav );
							cavalryLost += ( int ) ( 0.04 * attackCav );
							attackCav = 0;
						}
						
						attackPoints = attackCav;
						if( attackPoints < 500 ) {
							// Let's not get into an endless loop where we only lose 1 or 0 attack points per run
							attackPoints = 0;
						}
					}
					
					rs3 = stmt3.executeQuery( "SELECT name " +
							"FROM ruler " +
							"WHERE ruler_id = " + ruler_id );
					rs3.next();
					String name = rs3.getString( "name" );
					
					String name2 = "";
					if( ruler_id2 == -1 ) {
						name2 = "Independent forces";
					}
					else {
						rs3 = stmt3.executeQuery( "SELECT name FROM ruler WHERE ruler_id = " + ruler_id2 );
						rs3.next();
						name2 = rs3.getString( "name" );
					}
					
					rs3 = stmt3.executeQuery( "SELECT name FROM faction_member " +
							"JOIN faction ON faction.faction_id = faction_member.faction_id " +
							"WHERE invited = 0 AND requested = 0 AND ruler_id = " + ruler_id2 );
					String faction2 = "";
					if( rs3.next() ) {
						faction2 = " from " + rs3.getString( "name" );
					}
					String faction = "";
					if( faction_id != -1 ) {
						rs3 = stmt3.executeQuery( "SELECT name FROM faction " +
								"WHERE faction_id = " + faction_id );
						rs3.next();
						faction = " from " + rs3.getString( "name" );
					}
					
					// Let's write a report and update the armies, rulers and officers
					
					
					long experienceGained = scoutsLost * 32l + infantryLost * 48l + cavalryLost * 256l + artilleryLost * 400l; 
					stmtUpdate.execute( "UPDATE ruler SET experience = experience + " + experienceGained +  
							", scouts_killed = scouts_killed + " + scoutsLost + ", infantry_killed = infantry_killed + " + infantryLost + 
							", cavalry_killed = cavalry_killed + " + cavalryLost + ", artillery_killed = artillery_killed + " + artilleryLost +
							" WHERE ruler_id = " + ruler_id );
					stmtUpdate.execute( "UPDATE ruler SET experience = experience + " + ( long ) ( experienceGained * 0.5 ) +  
							", scouts_lost = scouts_lost + " + scoutsLost + ", infantry_lost = infantry_lost + " + infantryLost + 
							", cavalry_lost = cavalry_lost + " + cavalryLost + ", artillery_lost = artillery_lost + " + artilleryLost +
							" WHERE ruler_id = " + ruler_id2 );
					
					stmtUpdate.execute( "UPDATE army SET scout = " + scout2 + ", infantry = " + infantry2 + ", cavalry = " + cavalry2 + ", artillery = " + artillery2 + 
							" WHERE army_id = " + army_id2 );
					
					stmtUpdate.execute( "UPDATE officers SET experience = experience + " + experienceGained + 
							" WHERE officer_id = " + officer_id );
					
					stmtUpdate.execute( "UPDATE officers SET experience = experience + " + ( long ) ( experienceGained * 0.5 ) + 
							" WHERE officer_id = " + officer_id2 );
					
					//stmtUpdate.execute( "UPDATE army SET scout = " + scout2 + ", infantry = " + infantry2 + ", cavalry = " + cavalry2 + ", artillery = " + artillery2 + 
					//		" WHERE army_id = " + army_id2 );
					if( scout2 == 0 && infantry2 == 0 && cavalry2 == 0 && artillery2 == 0 && travel != 0 ) {
						stmtUpdate.execute( "DELETE FROM army " + 
								" WHERE army_id = " + army_id2 );
						stmtUpdate.execute( "DELETE FROM army_orders " + 
								" WHERE army_id = " + army_id2 );
					}
					else {
						stmtUpdate.execute( "UPDATE army SET scout = " + scout2 + ", infantry = " + infantry2 + ", cavalry = " + cavalry2 + ", artillery = " + artillery2 + 
								" WHERE army_id = " + army_id2 );
					}
					
					newsItem.clear();
					
					newsItem.addTitleText( "Bombardment report", true );
					newsItem.addTitleText( ": " + armyName, false );
					
					newsItem.addText( "Our army", true );
					newsItem.addText( " " + armyName + " ", false );
					newsItem.addText( "at", true );
					newsItem.addText( " <a href=\"../operations/map.php?x=" + ( x - 20 ) + "&y=" + ( y - 20 ) + "\">(" + x + ", " + y + ")</a>  ", false );
					newsItem.addText( "is bombarding", true );
					newsItem.addText( " " + armyName2 + ", ", false );
					newsItem.addText( "owned by", true );
					newsItem.addText( " ", false );
					newsItem.addText( name2, false );
					newsItem.addText( faction2 + ".\n", false );
					
					newsItem.addText( "\n<strong class=\"artillery\">" + Utils.formatNumber( "" + artillery ) + "</strong> ", false );
					newsItem.addText( "units of artillery are firing", true );
					newsItem.addText( ".\n\n<table class=\"news-table\"><tr><th>", false );
					newsItem.addText( "Unit", true );
					newsItem.addText( "</th><th>", false );
					newsItem.addText( "Before", true );
					newsItem.addText( "</th><th>", false );
					newsItem.addText( "Lost", true );
					newsItem.addText( "</th><th>", false );
					newsItem.addText( "After", true );
					newsItem.addText( "</th></tr><tr><td>", false );
					newsItem.addText( "Scouts", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + ( scout2 + scoutsLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + scoutsLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + scout2 ) + "</strong></td></tr><tr><td>", false );
					newsItem.addText( "Infantry", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + ( infantry2 + infantryLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + infantryLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + infantry2 ) + "</strong></td></tr><tr><td>", false );
					newsItem.addText( "Cavalry", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + ( cavalry2 + cavalryLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalryLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalry2 ) + "</strong></td></tr><tr><td>", false );
					newsItem.addText( "Artillery", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + ( artillery2 + artilleryLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + artilleryLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + artillery2 ) + "</strong></td></tr></table>", false );
					
					newsItem.insert( ruler_id, 0, turn, date );

					newsItem.clear();
					
					newsItem.addTitleText( armyName2 + " ", false );
					newsItem.addTitleText( "is being bombarded", true );
					
					newsItem.addText( "A hostile army", true );
					newsItem.addText( " " + armyName + " ", false );
					newsItem.addText( "is firing at our army", true );
					newsItem.addText( " " + armyName2 + " ", false );
					newsItem.addText( "from", true );
					newsItem.addText( " <a href=\"../operations/map.php?x=" + ( x - 20 ) + "&y=" + ( y - 20 ) + "\">(" + x + ", " + y + ")</a>.\n" + armyName + " ", false );
					newsItem.addText( "is owned by", true );
					newsItem.addText( " ", false );
					newsItem.addText( name, false );
					newsItem.addText( faction + ".\n", false );
					
					newsItem.addText( "\n<strong class=\"artillery\">" + Utils.formatNumber( "" + artillery ) + "</strong> ", false );
					newsItem.addText( "units of artillery are firing", true );
					newsItem.addText( ".\n\n<table class=\"news-table\"><tr><th>", false );
					newsItem.addText( "Unit", true );
					newsItem.addText( "</th><th>", false );
					newsItem.addText( "Before", true );
					newsItem.addText( "</th><th>", false );
					newsItem.addText( "Lost", true );
					newsItem.addText( "</th><th>", false );
					newsItem.addText( "After", true );
					newsItem.addText( "</th></tr><tr><td>", false );
					newsItem.addText( "Scouts", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + ( scout2 + scoutsLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + scoutsLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + scout2 ) + "</strong></td></tr><tr><td>", false );
					newsItem.addText( "Infantry", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + ( infantry2 + infantryLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + infantryLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + infantry2 ) + "</strong></td></tr><tr><td>", false );
					newsItem.addText( "Cavalry", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + ( cavalry2 + cavalryLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalryLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalry2 ) + "</strong></td></tr><tr><td>", false );
					newsItem.addText( "Artillery", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + ( artillery2 + artilleryLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + artilleryLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + artillery2 ) + "</strong></td></tr></table>", false );
					
					newsItem.insert( ruler_id2, 0, turn, date );
				}
			}
		}
	}
	
	private void resolveIdleArmies() throws SQLException, NoSuchAlgorithmException {
		rs = stmt.executeQuery( "SELECT * FROM army " +
				"JOIN officers ON officers.officer_id = army.officer_id " +
				"WHERE artillery > 0 AND mission = 0 AND training = 0 AND travel = 0 AND fortified = 0 AND " +
					"( SELECT count(*) FROM army_orders WHERE army_orders.army_id = army.army_id ) = 0 " +
				"ORDER BY RAND()" );
		while ( rs.next() ) {
			AgesOfStrifeServer.log.debug( "Idle army ready to shoot, looking for target..." );
			int officer_id = rs.getInt( "officer_id" );
			String armyName = rs.getString( "name" );
			int ruler_id = rs.getInt( "ruler_id" );
			int officerOffenseBonus = rs.getInt( "offense" );
			rs2 = stmt2.executeQuery( "SELECT faction_id FROM faction_member WHERE requested = 0 AND invited = 0 AND ruler_id = " + ruler_id );
			int faction_id = -1;
			if( rs2.next() ) {
				faction_id = rs2.getInt( "faction_id" );
			}
			int artillery = rs.getInt( "artillery" );
			int x = rs.getInt( "x" );
			int y = rs.getInt( "y" );
			// Check if the army is not already in battle
			if( faction_id == -1 ) {
				rs2 = stmt2.executeQuery( "SELECT count( army_id ) FROM army " +
						"WHERE actual_x + 0.5 >= " + x + " AND actual_x - 0.5 < " + x + " AND actual_y + 0.5 >= " + y + " AND actual_y - 0.5 < " + y + " " +
						" AND army.ruler_id != " + ruler_id  );
			}
			else {
				rs2 = stmt2.executeQuery( "SELECT count( army_id ) FROM army " +
						"WHERE actual_x + 0.5 >= " + x + " AND actual_x - 0.5 < " + x + " AND actual_y + 0.5 >= " + y + " AND actual_y - 0.5 < " + y + " " +
						"AND army.ruler_id NOT IN ( SELECT ruler_id FROM faction_member WHERE faction_id = " + faction_id + " AND requested = 0 AND invited = 0 )" );
			}
			rs2.next();
			if( rs2.getInt( 1 ) == 0 ) { 
				// Only armies out of battle bombard
				if( faction_id == -1 ) {
					rs2 = stmt2.executeQuery( "SELECT * FROM army " +
							"WHERE " + x + " >= actual_x - 1 AND " + x + " <= actual_x + 1 AND " +
							y + " >= actual_y - 1 AND " + y + " <= actual_y + 1 AND army.ruler_id != " + ruler_id + " AND " +
							"( scout > 0 OR infantry > 0 OR cavalry > 0 OR artillery > 0 ) " +
							"ORDER BY RAND() LIMIT 1" );
				}
				else {
					rs2 = stmt2.executeQuery( "SELECT * FROM army " +
							"WHERE " + x + " >= actual_x - 1 AND " + x + " <= actual_x + 1 AND " +
							y + " >= actual_y - 1 AND " + y + " <= actual_y + 1 AND " +
							"( scout > 0 OR infantry > 0 OR cavalry > 0 OR artillery > 0 ) " +
							"AND army.ruler_id NOT IN ( SELECT ruler_id FROM faction_member WHERE faction_id = " + faction_id + " AND requested = 0 AND invited = 0 ) " +
							"ORDER BY RAND() LIMIT 1" );
				}
				
				if( rs2.next() ) {
					AgesOfStrifeServer.log.debug( "Bombarding!" );
					int army_id2 = rs2.getInt( "army_id" );
					int officer_id2 = rs2.getInt( "officer_id" );
					String armyName2 = rs2.getString( "name" );
					int ruler_id2 = rs2.getInt( "ruler_id" );
					int officerDefenseBonus = 0;
					if( officer_id2 != -1 ) {
						rs3 = stmt3.executeQuery( "SELECT defense " +
								"FROM officers " +
								"WHERE officer_id = " + officer_id );
						rs3.next();
						officerDefenseBonus = rs3.getInt( "defense" );
					}
						
					int scout2 = rs2.getInt( "scout" );
					int infantry2 = rs2.getInt( "infantry" );
					int cavalry2 = rs2.getInt( "cavalry" );
					int artillery2 = rs2.getInt( "artillery" );
					int travel = rs2.getInt( "travel" );
					int fortified2 = rs2.getInt( "fortified" );

					int scoutsLost = 0;
					int infantryLost = 0;
					int cavalryLost = 0;
					int artilleryLost = 0;

					double bonus = 1.0;
					int faction_id2 = -1;
					rs3 = stmt3.executeQuery( "SELECT faction_id " +
							"FROM faction_member " +
							"WHERE ruler_id = " + ruler_id2 + " AND requested = 0 AND invited = 0" );
					if( rs3.next() ) {
						faction_id2 = rs3.getInt( "faction_id" );
					}
					if( faction_id2 != -1 ) {
						rs3 = stmt3.executeQuery( "SELECT SUM( defense_bonus ) " +
								"FROM village_buildings " +
								"JOIN buildings ON buildings.building_id = village_buildings.building_id " +
								"JOIN village ON village.village_id = village_buildings.village_id " +
								"JOIN faction_member ON faction_member.ruler_id = village.ruler_id " +
								"WHERE x = " + ( int ) Math.round( rs2.getDouble( "actual_x" ) ) + " AND y = " + ( int ) Math.round( rs2.getDouble( "actual_y" ) ) + " AND faction_id = " + faction_id2 );
					}
					else {
						rs3 = stmt3.executeQuery( "SELECT SUM( defense_bonus ) " +
								"FROM village_buildings " +
								"JOIN buildings ON buildings.building_id = village_buildings.building_id " +
								"JOIN village ON village.village_id = village_buildings.village_id " +
								"WHERE x = " + ( int ) Math.round( rs2.getDouble( "actual_x" ) ) + " AND y = " + ( int ) Math.round( rs2.getDouble( "actual_y" ) ) + " AND ruler_id = " + ruler_id2 );
					}
					rs3.next();
					bonus -= rs3.getDouble( 1 );
					if( faction_id != -1 ) {
						rs3 = stmt3.executeQuery( "SELECT SUM( offense_bonus ) " +
								"FROM village_buildings " +
								"JOIN buildings ON buildings.building_id = village_buildings.building_id " +
								"JOIN village ON village.village_id = village_buildings.village_id " +
								"JOIN faction_member ON faction_member.ruler_id = village.ruler_id " +
								"WHERE x = " + x + " AND y = " + y + " AND faction_id = " + faction_id );
					}
					else {
						rs3 = stmt3.executeQuery( "SELECT SUM( offense_bonus ) " +
								"FROM village_buildings " +
								"JOIN buildings ON buildings.building_id = village_buildings.building_id " +
								"JOIN village ON village.village_id = village_buildings.village_id " +
								"WHERE x = " + x + " AND y = " + y + " AND ruler_id = " + ruler_id );
					}
					rs3.next();
					bonus += rs3.getDouble( 1 );
					bonus -= ( officerDefenseBonus * 0.02 );
					bonus += ( officerOffenseBonus * 0.02 );
					if( fortified2 == 1 ) {
						bonus -= 0.2;
					}
					
					if( bonus < 0 ) {
						bonus = 0;
					}
					// Calculate the attack points for the bombardment
					long attackPoints = ( int ) ( artillery * 0.8 * bonus );
					while( attackPoints > 0 && ( scout2 + infantry2 + cavalry2 + artillery2 != 0 ) ) {
						// While there are attack points left we divide them to target specific groups
						AgesOfStrifeServer.log.debug( "Attack points: " + attackPoints );
						int attackInf = ( int ) ( 0.4 * attackPoints );
						int attackScouts = ( int ) ( 0.04 * attackPoints );
						int attackCav = ( int ) ( 0.28 * attackPoints );;
						int attackArt = attackCav;
						if( scout2 < attackScouts ) {
							attackScouts -= scout2;
							scoutsLost += scout2;
							scout2 = 0;
							attackInf += attackScouts;
						}
						else {
							scoutsLost += attackScouts;
							scout2 -= attackScouts;
						}
						attackScouts = 0;
						
						if( infantry2 < attackInf * 0.25 ) {
							attackInf -= infantry2 * 4;
							infantryLost += infantry2;
							infantry2 = 0;
							attackArt += attackInf;
						}
						else {
							infantry2 -= ( int ) ( 0.25 * attackInf );
							infantryLost += ( int ) ( 0.25 * attackInf );
						}
						attackInf = 0;
						
						if( artillery2 * 25 < attackArt ) {
							attackArt -= artillery2 * 25;
							artilleryLost += artillery2;
							artillery2 = 0;
							attackCav += attackArt;
						}
						else {
							artillery2 -= ( int ) ( attackArt * 0.04 );
							artilleryLost += ( int ) ( attackArt * 0.04 );
						}
						attackArt = 0;
						
						if( cavalry2 * 25 < attackCav ) {
							attackCav -= cavalry2 * 25;
							cavalryLost += cavalry2;
							cavalry2 = 0;
						}
						else {
							cavalry2 -= ( int ) ( 0.04 * attackCav );
							cavalryLost += ( int ) ( 0.04 * attackCav );
							attackCav = 0;
						}
						
						attackPoints = attackCav;
						if( attackPoints < 500 ) {
							// Let's not get into an endless loop where we only lose 1 or 0 attack points per run
							attackPoints = 0;
						}
					}
					
					rs3 = stmt3.executeQuery( "SELECT name FROM ruler WHERE ruler_id = " + ruler_id );
					String name;
					boolean translateName = false;
					if( rs3.next() ) {
						name = rs3.getString( "name" );
					}
					else {
						name = "Independent forces";
						translateName = true;
					}
					
					String name2 = "";
					boolean translateName2 = false;
					if( ruler_id2 == -1 ) {
						name2 = "Independent forces";
						translateName2 = true;
					}
					else {
						rs3 = stmt3.executeQuery( "SELECT name FROM ruler WHERE ruler_id = " + ruler_id2 );
						rs3.next();
						name2 = rs3.getString( "name" );
					}
					
					rs3 = stmt3.executeQuery( "SELECT name FROM faction_member " +
							"JOIN faction ON faction.faction_id = faction_member.faction_id " +
							"WHERE invited = 0 AND requested = 0 AND ruler_id = " + ruler_id2 );
					String faction2 = "";
					if( rs3.next() ) {
						faction2 = " from " + rs3.getString( "name" );
					}
					String faction = "";
					if( faction_id != -1 ) {
						rs3 = stmt3.executeQuery( "SELECT name FROM faction " +
								"WHERE faction_id = " + faction_id );
						rs3.next();
						faction = " from " + rs3.getString( "name" );
					}
					
					// Let's write a report and update the armies, rulers and officers
					
					long experienceGained = scoutsLost * 32l + infantryLost * 48l + cavalryLost * 256l + artilleryLost * 400l; 
					stmtUpdate.execute( "UPDATE ruler SET experience = experience + " + experienceGained +  
							", scouts_killed = scouts_killed + " + scoutsLost + ", infantry_killed = infantry_killed + " + infantryLost + 
							", cavalry_killed = cavalry_killed + " + cavalryLost + ", artillery_killed = artillery_killed + " + artilleryLost +
							" WHERE ruler_id = " + ruler_id );
					stmtUpdate.execute( "UPDATE ruler SET experience = experience + " + ( long ) ( experienceGained * 0.5 ) +  
							", scouts_lost = scouts_lost + " + scoutsLost + ", infantry_lost = infantry_lost + " + infantryLost + 
							", cavalry_lost = cavalry_lost + " + cavalryLost + ", artillery_lost = artillery_lost + " + artilleryLost +
							" WHERE ruler_id = " + ruler_id2 );
					
					stmtUpdate.execute( "UPDATE army SET scout = " + scout2 + ", infantry = " + infantry2 + ", cavalry = " + cavalry2 + ", artillery = " + artillery2 + 
							" WHERE army_id = " + army_id2 );
					
					stmtUpdate.execute( "UPDATE officers " +
							"SET experience = experience + " + experienceGained + 
							" WHERE officer_id = " + officer_id );
					
					stmtUpdate.execute( "UPDATE officers " +
							"SET experience = experience + " + ( long ) ( experienceGained * 0.5 ) + 
							" WHERE officer_id = " + officer_id2 );
					
					//stmtUpdate.execute( "UPDATE army SET scout = " + scout2 + ", infantry = " + infantry2 + ", cavalry = " + cavalry2 + ", artillery = " + artillery2 + 
					//		" WHERE army_id = " + army_id2 );
					if( scout2 == 0 && infantry2 == 0 && cavalry2 == 0 && artillery2 == 0 && travel != 0 ) {
						stmtUpdate.execute( "DELETE FROM army " + 
								" WHERE army_id = " + army_id2 );
						stmtUpdate.execute( "DELETE FROM army_orders " + 
								" WHERE army_id = " + army_id2 );
					}
					else {
						stmtUpdate.execute( "UPDATE army SET scout = " + scout2 + ", infantry = " + infantry2 + ", cavalry = " + cavalry2 + ", artillery = " + artillery2 + 
								" WHERE army_id = " + army_id2 );
					}
					newsItem.clear();
					
					newsItem.addTitleText( "Idle army artillery fire", true );
					newsItem.addTitleText( ": " + armyName, false );
					
					newsItem.addText( "Our army", true );
					newsItem.addText( " " + armyName + " ", false );
					newsItem.addText( "at", true );
					newsItem.addText( " <a href=\"../operations/map.php?x=" + ( x - 20 ) + "&y=" + ( y - 20 ) + "\">(" + x + ", " + y + ")</a>  ", false );
					newsItem.addText( "is bombarding", true );
					newsItem.addText( " " + armyName2 + ", ", false );
					newsItem.addText( "owned by", true );
					newsItem.addText( " ", false );
					newsItem.addText( name2, translateName2 );
					newsItem.addText( faction2 + ".\n", false );
					
					newsItem.addText( "\n<strong class=\"artillery\">" + Utils.formatNumber( "" + artillery ) + "</strong> ", false );
					newsItem.addText( "units of artillery are firing", true );
					newsItem.addText( ".\n\n<table class=\"news-table\"><tr><th>", false );
					newsItem.addText( "Unit", true );
					newsItem.addText( "</th><th>", false );
					newsItem.addText( "Before", true );
					newsItem.addText( "</th><th>", false );
					newsItem.addText( "Lost", true );
					newsItem.addText( "</th><th>", false );
					newsItem.addText( "After", true );
					newsItem.addText( "</th></tr><tr><td>", false );
					newsItem.addText( "Scouts", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + ( scout2 + scoutsLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + scoutsLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + scout2 ) + "</strong></td></tr><tr><td>", false );
					newsItem.addText( "Infantry", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + ( infantry2 + infantryLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + infantryLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + infantry2 ) + "</strong></td></tr><tr><td>", false );
					newsItem.addText( "Cavalry", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + ( cavalry2 + cavalryLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalryLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalry2 ) + "</strong></td></tr><tr><td>", false );
					newsItem.addText( "Artillery", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + ( artillery2 + artilleryLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + artilleryLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + artillery2 ) + "</strong></td></tr></table>", false );
					
					newsItem.insert( ruler_id, 0, turn, date );

					newsItem.clear();
					
					newsItem.addTitleText( armyName2 + " ", false );
					newsItem.addTitleText( "is being bombarded", true );
					
					newsItem.addText( "A hostile army", true );
					newsItem.addText( " " + armyName + " ", false );
					newsItem.addText( "is firing at our army", true );
					newsItem.addText( " " + armyName2 + " ", false );
					newsItem.addText( "from", true );
					newsItem.addText( " <a href=\"../operations/map.php?x=" + ( x - 20 ) + "&y=" + ( y - 20 ) + "\">(" + x + ", " + y + ")</a>.\n" + armyName + " ", false );
					newsItem.addText( "is owned by", true );
					newsItem.addText( " ", false );
					newsItem.addText( name, translateName );
					newsItem.addText( faction + ".\n", false );
					
					newsItem.addText( "\n<strong class=\"artillery\">" + Utils.formatNumber( "" + artillery ) + "</strong> ", false );
					newsItem.addText( "units of artillery are firing", true );
					newsItem.addText( ".\n\n<table class=\"news-table\"><tr><th>", false );
					newsItem.addText( "Unit", true );
					newsItem.addText( "</th><th>", false );
					newsItem.addText( "Before", true );
					newsItem.addText( "</th><th>", false );
					newsItem.addText( "Lost", true );
					newsItem.addText( "</th><th>", false );
					newsItem.addText( "After", true );
					newsItem.addText( "</th></tr><tr><td>", false );
					newsItem.addText( "Scouts", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + ( scout2 + scoutsLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + scoutsLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + scout2 ) + "</strong></td></tr><tr><td>", false );
					newsItem.addText( "Infantry", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + ( infantry2 + infantryLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + infantryLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + infantry2 ) + "</strong></td></tr><tr><td>", false );
					newsItem.addText( "Cavalry", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + ( cavalry2 + cavalryLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalryLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalry2 ) + "</strong></td></tr><tr><td>", false );
					newsItem.addText( "Artillery", true );
					newsItem.addText( "</td><td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + ( artillery2 + artilleryLost ) ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + artilleryLost ) + "</strong></td>" +
							"<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + artillery2 ) + "</strong></td></tr></table>", false );
					
					newsItem.insert( ruler_id2, 0, turn, date );
				}
			}
		}
	}

	private void updateVisibleArmies( int turns_inactive ) throws SQLException {
		stmtUpdate.execute( "DELETE FROM army_visible" );
		rs = stmt.executeQuery( "SELECT ruler_id FROM ruler WHERE resigned = 0 AND active_turn > " + ( turn - turns_inactive ) );
		while( rs.next() ) {
			int ruler_id = rs.getInt( "ruler_id" );
			HashMap<String, String> hashMap = new HashMap<String, String>();
			rs2 = stmt2.executeQuery( "SELECT x, y, building_id FROM village " +
					"JOIN village_buildings ON village.village_id = village_buildings.village_id " +
					"WHERE ruler_id = " + ruler_id  + " " +
							"AND ( ( building_id = 21 AND " +
								"( SELECT count(*) FROM village_buildings AS second_buildings WHERE second_buildings.village_id = village_buildings.village_id AND second_buildings.building_id = 25 ) = 0 ) " +
							"OR building_id = 25 )" );
			while( rs2.next() ) {
				int x = rs2.getInt( "x" );
				int y = rs2.getInt( "y" );
				int building_id = rs2.getInt( "building_id" );
				int difference;
				
				if( building_id == 25 ) {
					difference = 20;
				}
				else {
					difference = 8;
				}
				
				rs3 = stmt3.executeQuery( "SELECT army_id FROM army " +
						"WHERE actual_x > " + ( x - difference ) + " AND actual_x < " + ( x + difference ) +
						" AND NOT ( infantry + cavalry + artillery = 0 AND scout = 1 AND officer_id = -1 AND ruler_id != " + ruler_id + ") " + 
						" AND actual_y > " + ( y - difference ) + " AND actual_y < " + ( y + difference ) );
				while( rs3.next() ) {
					if( hashMap.get( "" + rs3.getInt( "army_id" ) ) == null ) {
						rs4 = stmt4.executeQuery( "SELECT complete_turn FROM army_orders " +
								"WHERE rank = 0 AND army_id = " + rs3.getInt( "army_id" ) + " AND order_type = 1" );
						int eta = 0;
						if( rs4.next() && rs4.getInt( "complete_turn" ) > 0 ) {
							eta = rs4.getInt( "complete_turn" ) - turn;
						}
						stmtUpdate.execute( "INSERT INTO army_visible ( ruler_id, army_id, eta ) " +
								"VALUES ( " + ruler_id + ", " + rs3.getInt( "army_id" ) + ", " + eta + " )" );
						hashMap.put( ( "" + rs3.getInt( "army_id" ) ), "" + rs3.getInt( "army_id" ) );
					}
				}
			}
			rs2 = stmt2.executeQuery( "SELECT x, y, travel, actual_x, actual_y, officer_id " +
					"FROM army " +
					"WHERE ruler_id = " + ruler_id + " AND scout + infantry + cavalry + artillery > 0" );
			while( rs2.next() ) {
				int x = -1;
				int y = -1;
				int scouting = 0;
				int officer_id = rs2.getInt( "officer_id" );
				
				if( officer_id > -1 ) {
					rs3 = stmt3.executeQuery( "SELECT scouting " +
							"FROM officers " +
							"WHERE officer_id = " + officer_id );
					if( rs3.next() ) {
						scouting = rs3.getInt( "scouting" );
					}
				}
				if( rs2.getInt( "travel" ) > 0 ) {
					x = ( int ) ( rs2.getDouble( "actual_x" ) + 0.5 );
					y = ( int ) ( rs2.getDouble( "actual_y" ) + 0.5 );
				}
				else {
					x = rs2.getInt( "x" );
					y = rs2.getInt( "y" );
				}
				rs3 = stmt3.executeQuery( "SELECT army_id FROM army " +
						"WHERE actual_x > " + ( x - ( 3 + scouting ) ) + " AND actual_x < " + ( x + ( 3 + scouting ) ) + 
						" AND actual_y > " + ( y - ( 3 + scouting ) ) + " AND actual_y < " + ( y + ( 3 + scouting ) ) + 
						" AND NOT ( infantry + cavalry + artillery = 0 AND scout = 1 AND officer_id = -1 AND ruler_id != " + ruler_id + ")" );
				while( rs3.next() ) {
					if( hashMap.get( "" + rs3.getInt( "army_id" ) ) == null ) {
						rs4 = stmt4.executeQuery( "SELECT complete_turn FROM army_orders " +
								"WHERE rank = 0 AND army_id = " + rs3.getInt( "army_id" ) + " AND order_type = 1" );
						int eta = 0;
						if( rs4.next() && rs4.getInt( "complete_turn" ) > 0 ) {
							eta = rs4.getInt( "complete_turn" ) - turn;
						}
						stmtUpdate.execute( "INSERT INTO army_visible ( ruler_id, army_id, eta ) " +
								"VALUES ( " + ruler_id + ", " + rs3.getInt( "army_id" ) + ", " + eta + " )" );
						hashMap.put( "" + rs3.getInt( "army_id" ), "" + rs3.getInt( "army_id" ) );
					}
				}
			}
		}
	}

	private void updateExpeditons() throws SQLException, NoSuchAlgorithmException {
		rs = stmt.executeQuery( "SELECT * " +
				"FROM ruler_expedition " +
				"JOIN expeditions ON expeditions.expedition_id = ruler_expedition.expedition_id " +
				"WHERE complete_turn <= " + turn + " AND completed = 0 AND started = 1" );
		while ( rs.next() ) {
			AgesOfStrifeServer.log.debug( "An expedition has finished: " + rs.getString( "name" ) );
			int gold_return = ( int ) ( ( Math.random() * rs.getInt( "gold_return" ) * 0.05 ) + rs.getInt( "gold_return" ) * 0.975 );
			int coal_return = ( int ) ( ( Math.random() * rs.getInt( "coal_return" ) * 0.05 ) + rs.getInt( "coal_return" ) * 0.975 );
			int iron_return = ( int ) ( ( Math.random() * rs.getInt( "iron_return" ) * 0.05 ) + rs.getInt( "iron_return" ) * 0.975 );
			int recruits_return = ( int ) ( ( Math.random() * rs.getInt( "recruit_return" ) * 0.05 ) + rs.getInt( "recruit_return" ) * 0.975 );
			int scouts_return = ( int ) ( ( Math.random() * rs.getInt( "scouts_return" ) * 0.05 ) + rs.getInt( "scouts_return" ) * 0.975 );
			int infantry_return = ( int ) ( ( Math.random() * rs.getInt( "infantry_return" ) * 0.05 ) + rs.getInt( "infantry_return" ) * 0.975 );
			int cavalry_return = ( int ) ( ( Math.random() * rs.getInt( "cavalry_return" ) * 0.05 ) + rs.getInt( "cavalry_return" ) * 0.975 );
			int artillery_return = ( int ) ( ( Math.random() * rs.getInt( "artillery_return" ) * 0.05 ) + rs.getInt( "artillery_return" ) * 0.975 );
			int ruler_id = rs.getInt( "ruler_id" );
			int ruler_expedition_id = rs.getInt( "ruler_expedition_id" );
			int expedition_id = rs.getInt( "expedition_id" );
			int repeat = rs.getInt( "repeat" );
			
			rs2 = stmt2.executeQuery( "SELECT * FROM ruler WHERE ruler_id = " + ruler_id );
			if( rs2.next() ) {
				int gold = rs2.getInt( "gold" );
				int coal = rs2.getInt( "coal" );
				int iron = rs2.getInt( "iron" );
				int recruits = rs2.getInt( "recruits" );
				int scouts = rs2.getInt( "scouts" );
				int infantry = rs2.getInt( "infantry" );
				int cavalry = rs2.getInt( "cavalry" );
				int artillery = rs2.getInt( "artillery" );
				
				stmtUpdate.executeUpdate( "UPDATE ruler SET gold = " + ( gold + gold_return ) + ", " +
										  "coal = " + ( coal + coal_return ) + ", " +
										  "iron = " + ( iron + iron_return ) + ", " + 
										  "recruits = " + ( recruits + recruits_return ) + ", " + 
										  "scouts = " + ( scouts + scouts_return ) + ", " + 
										  "infantry = " + ( infantry + infantry_return ) + ", " + 
										  "cavalry = " + ( cavalry + cavalry_return ) + ", " + 
										  "artillery = " + ( artillery + artillery_return ) + 
										  " WHERE ruler_id = " + ruler_id );
				
				if( repeat == 1 ) {
					rs3 = stmt3.executeQuery( "SELECT count(*) " +
							"FROM ruler_expedition " +
							"WHERE completed = 0 AND ruler_id = " + ruler_id );
					if( rs3.next() ) {
						int count = rs3.getInt( 1 );
						int pending = 0;
						if( count == 0 ) {
							pending = 1;
						}
						PreparedStatement preparedStatement = con.prepareStatement( "INSERT INTO ruler_expedition " +
								"( `ruler_id`, `expedition_id`, `rank`, `pending`, `repeat` ) " +
								"VALUES ( ?, ?, ?, ?, ? )" );
						preparedStatement.setInt( 1, ruler_id );
						preparedStatement.setInt( 2, expedition_id );
						preparedStatement.setInt( 3, count );
						preparedStatement.setInt( 4, pending );
						preparedStatement.setInt( 5, repeat );
						preparedStatement.execute();
					}
				}
				stmtUpdate.executeUpdate( "UPDATE ruler_expedition " +
						"SET completed = 1, complete_turn = " + turn + ", " +
						" complete_date = '" + date + "' " +
								"WHERE ruler_expedition_id = " + ruler_expedition_id );
				
				newsItem.clear();
				newsItem.addTitleText( "An expedition force has returned", true );
				newsItem.addText( "The expedition force returned with:", true );
				newsItem.addText( "\n", false );
				
				if( gold_return > 0 ) {
					newsItem.addText( "Gold returned:", true );
					newsItem.addText( " <strong class=\"gold\">" + Utils.formatNumber( "" + gold_return ) + "</strong>\n", false );
				}
				if( iron_return > 0 ) {
					newsItem.addText( "Iron returned:", true );
					newsItem.addText( " <strong class=\"iron\">" + Utils.formatNumber( "" + iron_return ) + "</strong>\n", false );
				}
				if( coal_return > 0 ) {
					newsItem.addText( "Coal returned:", true );
					newsItem.addText( " <strong class=\"coal\">" + Utils.formatNumber( "" + coal_return ) + "</strong>\n", false );
				}
				if( recruits_return > 0 ) {
					newsItem.addText( "Recruits returned:", true );
					newsItem.addText( " <strong class=\"recruits\">" + Utils.formatNumber( "" + recruits_return ) + "</strong>\n", false );
				}
				if( scouts_return > 0 ) {
					newsItem.addText( "Scouts returned:", true );
					newsItem.addText( " <strong class=\"scouts\">" + Utils.formatNumber( "" + scouts_return ) + "</strong>\n", false );
				}
				if( infantry_return > 0 ) {
					newsItem.addText( "Infantry returned:", true );
					newsItem.addText( " <strong class=\"infantry\">" + Utils.formatNumber( "" + infantry_return ) + "</strong>\n", false );
				}
				if( cavalry_return > 0 ) {
					newsItem.addText( "Cavalry returned:", true );
					newsItem.addText( " <strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalry_return ) + "</strong>\n", false );
				}
				if( artillery_return > 0 ) {
					newsItem.addText( "Artillery returned:", true );
					newsItem.addText( " <strong class=\"artillery\">" + Utils.formatNumber( "" + artillery_return ) + "</strong>\n", false );
				}
				
				rs3 = stmt3.executeQuery( "SELECT count(*) " +
						"FROM ruler_expedition " +
						"WHERE completed = 0 AND ruler_id = " + ruler_id );
				if( rs3.next() && rs3.getInt( 1 ) == 0 ) {
					newsItem.addText( "\n", false );
					newsItem.addText( "Your expedition queue is now empty", true );
					newsItem.addText( ", ", false );
					newsItem.addText( "you can queue new expeditions <a href=\"../operations/expeditions.php\">here</a>.", true );
				}

				newsItem.insert( ruler_id, 0, turn, date );
			}
			rs2 = stmt2.executeQuery( "SELECT ruler_expedition_id, expedition_id FROM ruler_expedition WHERE completed = 0 AND ruler_id = " + ruler_id + " ORDER BY rank LIMIT 1" );
			if( rs2.next() ) {
				if( startExpedition( rs2.getInt( "ruler_expedition_id" ), ruler_id, rs2.getInt( "expedition_id" ) ) ) {
					rs3 = stmt3.executeQuery( "SELECT ruler_expedition_id, rank FROM ruler_expedition WHERE completed = 0 AND ruler_id = " + ruler_id + " ORDER BY rank" );
					while ( rs3.next() ) {
						stmtUpdate.executeUpdate( "UPDATE ruler_expedition SET rank = " + ( rs3.getInt( "rank" ) - 1 ) + 
								" WHERE ruler_expedition_id = " + rs3.getInt( "ruler_expedition_id" ) );
					}
				}
				else {
					stmtUpdate.execute( "UPDATE ruler_expedition SET pending = 1 WHERE ruler_expedition_id = " + rs2.getInt( "ruler_expedition_id" ) );
				}
			}
		}
		
		rs = stmt.executeQuery( "SELECT ruler_expedition_id, ruler_id, expedition_id FROM ruler_expedition WHERE pending = 1" );
		while ( rs.next() ) {
			startExpedition( rs.getInt( "ruler_expedition_id" ), rs.getInt( "ruler_id" ), rs.getInt( "expedition_id" ) );
		}
	}
	
	private boolean startExpedition( int ruler_expedition_id, int ruler_id, int expedition_id ) throws SQLException {
		boolean ret = false;
		
		rs3 = stmt3.executeQuery( "SELECT * FROM expeditions WHERE expedition_id = " + expedition_id );
		if( rs3.next() ) {
			rs4 = stmt4.executeQuery( "SELECT * FROM ruler WHERE ruler_id = " + ruler_id );
			if( rs4.next() ) {
				int gold = rs4.getInt( "gold" );
				int coal = rs4.getInt( "coal" );
				int iron = rs4.getInt( "iron" );
				int recruits = rs4.getInt( "recruits" );				
				int gold_cost = rs3.getInt( "gold_cost" );
				int coal_cost = rs3.getInt( "coal_cost" );
				int iron_cost = rs3.getInt( "iron_cost" );
				int recruits_cost = rs3.getInt( "recruit_cost" );
				if( gold >= gold_cost && iron >= iron_cost && coal >= coal_cost && recruits >= recruits_cost ) {
					int time_cost = rs3.getInt( "time_cost" ); 
					stmtUpdate.executeUpdate( "UPDATE ruler SET gold = " + ( gold - gold_cost ) + ", " +
							  "coal = " + ( coal - coal_cost ) + ", " +
							  "iron = " + ( iron - iron_cost ) + ", " + 
							  "recruits = " + ( recruits - recruits_cost ) + 
							  " WHERE ruler_id = " + ruler_id );
					stmtUpdate.executeUpdate( "UPDATE ruler_expedition SET started = 1, pending = 0, complete_turn = " + ( turn + time_cost - 1 ) + 
							", complete_date = '" + date + "' WHERE ruler_expedition_id = " + ruler_expedition_id );
					ret = true;
				}
			}
		}
		
		return ret;
	}

	private void sendNewsEmails() throws SQLException, SendFailedException, MessagingException {
		Properties properties = System.getProperties();
		properties.put( "mail.smtp.host", parent.getMailHost() );
		properties.put( "mail.smtp.port", parent.getMailPort() );
		properties.put( "mail.smtp.timeout", "30000" );
		Session session = Session.getInstance( properties, null );
		MimeMessage mimeMessage = new MimeMessage( session );
		
		String gameUrl = "";
		String roundName = "";
		int inactiveTurn = 480;
		rs = stmt.executeQuery( "SELECT gameurl, turns_inactive, round_name " +
				"FROM game" );
		if ( rs.next() ) {
			gameUrl = rs.getString( "gameurl" );
			roundName = rs.getString( "round_name" );
			inactiveTurn = rs.getInt( "turns_inactive" );
		}
		
		if( turn == 2 ) {
			rs = stmt.executeQuery( "SELECT open_shop " +
					"FROM game " +
					"LIMIT 1" );
			rs.next();
			if( rs.getInt( "open_shop" ) == 1 ) {
				// Send out newsletter about the start of the round if this is the main game
				rs = stmt.executeQuery( "SELECT email " +
						"FROM users " +
						"WHERE email != '' AND email LIKE '%@%' AND news_letter = 1" );
				while ( rs.next() ) {
					String newsMessage = "A new round of Ages of Strife has started:\n";
					newsMessage += roundName + "\n\n";
					newsMessage += "If you are not signed up yet join now!\n" +
							"\n" +
							"Good luck and have fun.\n\n";
						
					String emailMessage = newsMessage + "This message was automatically generated by the browser based strategy game Ages of Strife\n";
					emailMessage += "Ages of Strife: " + gameUrl + "/index.php\n\n";
	
					try {
						InternetAddress internetAddress = new InternetAddress( parent.getMailSender() );
						mimeMessage.setFrom( internetAddress );
						mimeMessage.setSubject( "Ages of Strife: New round started" );
						MimeMultipart mimeMultipart = new MimeMultipart();
						
						MimeBodyPart mimeBodyPart = new MimeBodyPart();
						mimeBodyPart.setText( emailMessage );
						mimeMultipart.addBodyPart( mimeBodyPart );
						mimeMessage.setContent( mimeMultipart );
						mimeMessage.setSentDate( new Date() );
						
						InternetAddress[] sendTo = new InternetAddress[1];
						sendTo[0] = new InternetAddress( rs.getString( "email" ) );
						
						Transport.send( mimeMessage, sendTo );
					} catch ( AddressException addressException ) {
						AgesOfStrifeServer.log.error( "Invalid e-mail address", addressException );
					} catch ( MessagingException messagingException ) {
						AgesOfStrifeServer.log.error( "Problem sending message", messagingException );
					}
				}
			}
		}
		
		rs = stmt.executeQuery( "SELECT ruler_id, name, email, users.user_id, letters, civilian_news, operations_news, military_news " +
				"FROM users " +
				"JOIN ruler ON users.user_id = ruler.user_id " +
				"WHERE email != '' AND email LIKE '%@%'" );
		while ( rs.next() ) {
			int ruler_id = rs.getInt( "ruler_id" );
			String newsMessage = "";
			if( rs.getString( "civilian_news" ).equals( "1" ) ) {
				rs2 = stmt2.executeQuery( "SELECT count(*) " +
						"FROM news " +
						"WHERE type = 2 AND ruler_id = " + ruler_id + " AND " +
								"( ( turn = " + turn + " AND seen = 0 ) " +
								"OR ( turn = " + ( turn - 1 ) + " AND seen = 0 AND subject = 'Independent village at%' ) )" );
				int total = 0;
				if( rs2.next() ) {
					total += rs2.getInt( "count(*)" );
				}
				
				if( total > 0 ) {
					newsMessage += "You received " + total + " new civilian news item";
					if( total > 1 ) {
						newsMessage += "s";
					}
					newsMessage += ":\n";
					rs2 = stmt2.executeQuery( "SELECT subject " +
							"FROM news " +
							"WHERE type = 2 AND ruler_id = " + ruler_id + " AND " +
									"( ( turn = " + turn + " AND seen = 0 ) " +
									"OR ( turn = " + ( turn - 1 ) + " AND seen = 0 AND subject = 'Independent village at%' ) )" );
					while( rs2.next() ) {
						newsMessage += " - " + rs2.getString( "subject" ) + "\n";
					}
					newsMessage += "\n";
				}
			}
			if( rs.getString( "military_news" ).equals( "1" ) ) {
				rs2 = stmt2.executeQuery( "SELECT count(*) " +
						"FROM news " +
						"WHERE type = 1 AND ruler_id = " + ruler_id + " AND " +
								"( ( turn = " + turn + " AND seen = 0 ) " +
								"OR ( turn = " + ( turn - 1 ) + " AND subject = 'Hostile army incoming'" + " AND seen = 0 ) )" );
				int total = 0;
				if( rs2.next() ) {
					total = rs2.getInt( "count(*)" );
				}

				if( total > 0 ) {
					newsMessage += "You received " + total + " new military news item";
					if( total > 1 ) {
						newsMessage += "s";
					}
					newsMessage += ":\n";
					rs2 = stmt2.executeQuery( "SELECT subject " +
							"FROM news " +
							"WHERE type = 1 AND ruler_id = " + ruler_id + " AND " +
									"( ( turn = " + turn + " AND seen = 0 ) " +
									"OR ( turn = " + ( turn - 1 ) + " AND subject = 'Hostile army incoming'" + " AND seen = 0 ) )" );
					while( rs2.next() ) {
						newsMessage += " - " + rs2.getString( "subject" ) + "\n";
					}
					newsMessage += "\n";
				}
			}
			if( rs.getString( "operations_news" ).equals( "1" ) ) {
				rs2 = stmt2.executeQuery( "SELECT count(*) " +
						"FROM news " +
						"WHERE type = 0 AND ruler_id = " + ruler_id + " AND turn = " + turn + " AND seen = 0" );
				if( rs2.next() ) {
					int total = rs2.getInt( "count(*)" );
					if( total > 0 ) {
						newsMessage += "You received " + total + " new operations news item";
						if( total > 1 ) {
							newsMessage += "s";
						}
						newsMessage += ":\n";
						rs2 = stmt2.executeQuery( "SELECT subject " +
								"FROM news " +
								"WHERE type = 0 AND ruler_id = " + ruler_id + " AND turn = " + turn + " AND seen = 0" );
						while( rs2.next() ) {
							newsMessage += " - " + rs2.getString( "subject" ) + "\n";
						}
						newsMessage += "\n";
					}
				}
			}
			if( rs.getString( "letters" ).equals( "1" ) ) {
				rs2 = stmt2.executeQuery( "SELECT count(*) " +
						"FROM messages " +
						"JOIN message_ruler ON messages.message_id = message_ruler.message_id " +
						"WHERE ruler_id = " + ruler_id + " AND turn = " + ( turn - 1 ) + " AND seen = 0" );
				if( rs2.next() ) {
					int total = rs2.getInt( "count(*)" );
					if( total > 0 ) {
						newsMessage += "You received " + total + " new letter";
						if( total > 1 ) {
							newsMessage += "s";
						}
						newsMessage += ":\n";
						rs2 = stmt2.executeQuery( "SELECT subject " +
								"FROM messages " +
								"JOIN message_ruler ON messages.message_id = message_ruler.message_id " +
								"WHERE ruler_id = " + ruler_id + " AND turn = " + ( turn - 1 ) + " AND seen = 0" );
						while( rs2.next() ) {
							newsMessage += " - " + rs2.getString( "subject" ) + "\n";
						}
						newsMessage += "\n";
					}
				}
			}
			
			if( newsMessage.length() > 0 ) {
				//AgesOfStrifeServer.log.debug( "Sending email notifier: " + newsMessage );
				
				String emailMessage = "This message was automatically generated by the browser based strategy game Ages of Strife\n\n";
				emailMessage += newsMessage;
				emailMessage += "Ages of Strife: " + gameUrl + "/index.php\n\n";
				// TODO add removal link, with auto generated code
				//emailMessage += "If you do not play ";

				emailMessage += "-- Ages of Strife e-mail notifier --";
				
				AgesOfStrifeServer.log.debug( "Email which should be sent: " + emailMessage );

				try {
					InternetAddress internetAddress = new InternetAddress( parent.getMailSender() );
					mimeMessage.setFrom( internetAddress );
					mimeMessage.setSubject( "Ages of Strife: notify e-mail" );
					MimeMultipart mimeMultipart = new MimeMultipart();
					
					MimeBodyPart mimeBodyPart = new MimeBodyPart();
					mimeBodyPart.setText( emailMessage );
					mimeMultipart.addBodyPart( mimeBodyPart );
					mimeMessage.setContent( mimeMultipart );
					mimeMessage.setSentDate( new Date() );
					
					InternetAddress[] sendTo = new InternetAddress[1];
					sendTo[0] = new InternetAddress( rs.getString( "email" ) );
					
					Transport.send( mimeMessage, sendTo );
				} catch ( AddressException addressException ) {
					AgesOfStrifeServer.log.error( "Invalid e-mail address", addressException );
				} catch ( MessagingException messagingException ) {
					AgesOfStrifeServer.log.error( "Problem sending message", messagingException );
				}
			}
		}
		
		
		String turns = "";
		boolean done = false;
		int nextTurn = turn - 48;
		int number = 0;
		while( !done ) {
			if( number > 0 ) {
				nextTurn = turn - number * 120;
			}
			number ++;
			if( nextTurn < 0 || nextTurn < turn - inactiveTurn ) {
				done = true;
			}
			else {
				if( turns != "" ) {
					turns += ", ";
				}
				turns += nextTurn;
			}
		}

		AgesOfStrifeServer.log.debug( "Active turns to look for: " + turns );
		
		if( turns != "" ) {
			rs = stmt.executeQuery( "SELECT email, gold, iron, coal, food, active_turn, ruler_id " +
					"FROM ruler " +
					"JOIN users ON ruler.user_id = users.user_id " +
					"WHERE inactivity_notification = 1 AND active_turn IN ( " + turns + " )" );
			
			while( rs.next() ) {
				String email = rs.getString( "email" );
				String subject = "Ages of Strife: reminder";
				String message;
				int gold = rs.getInt( "gold" );
				int iron = rs.getInt( "iron" );
				int coal = rs.getInt( "coal" );
				int food = rs.getInt( "food" );
				int rulerId = rs.getInt( "ruler_id" );
				int activeTurn = rs.getInt( "active_turn" );
				int inactivity = ( int ) Math.round( ( turn - activeTurn ) / 24.0 );
				
				rs2 = stmt2.executeQuery( "SELECT count(*) " +
						"FROM village_queue " +
						"JOIN village ON village.village_id = village_queue.village_id " +
						"WHERE ruler_id = " + rulerId );
				rs2.next();
				int construction = rs2.getInt( 1 );
				
				rs2 = stmt2.executeQuery( "SELECT count(*) " +
						"FROM upgrade_status " +
						"WHERE achieved = 0 AND ruler_id = " + rulerId );
				rs2.next();
				int upgrading = rs2.getInt( 1 );
				
				if( activeTurn == turn - inactiveTurn ) {
					// Last reminder, account will be inactive next turn
					message = "Hi,\n" +
						"\n" +
						"Your account at Ages of Strife has been inactive for " + inactivity + " days.\n" +
						"If you do not log in now your account will become inactive!\n" +
						"You can still log in later, but other players might have taken your villages and even your capital by then.\n";
				}
				else if( activeTurn == turn - ( inactiveTurn - 120 ) ) {
					// Last reminder before the end
					message = "Hi,\n" +
						"\n" +
						"You have received this email to remind you that you have not logged into Ages of Strife for " + inactivity + " days.\n" +
						"If you do not log in within the next 5 days your account will become inactive!\n";
				}
				else {
					message = "Hi,\n" +
							"\n" +
							"This is a reminder that you have not logged into Ages of Strife for " + inactivity + " days.\n";
				}
	
				message += "\n" +
						"You have gathered the following resources to spend or trade:\n" +
						Utils.formatNumber( "" + gold ) + " gold\n" +
						Utils.formatNumber( "" + iron ) + " iron\n" +
						Utils.formatNumber( "" + coal ) + " coal\n" +
						Utils.formatNumber( "" + food ) + " food\n" +
						"\n";
	
				if( construction == 0 ) {
					message += "You are not constructing any new buildings anymore!\n";
				}
				else if( construction == 1 ) {
					message += "You are only constructing one building at the moment!\n";
				}
				else {
					message += "You have " + construction + " buildings scheduled for construction.\n";
				}
				
				if( upgrading == 0 ) {
					message += "You are not doing any upgrades at the moment!\n";
				}
				else if( upgrading == 1 ) {
					message += "Your last queued upgrade is currently being completed!\n";
				}
				else {
					message += "You have " + upgrading + " upgrades queued.\n";
				}
				
				message += "\n" +
						"Log in now to continue expanding your empire:\n" +
						gameUrl + "\n" +
						"\n" +
						"Yours sincerely,\n" +
						"The Ages of Strife Team\n" +
						"\n" +
						"To no longer receive these emails, log into Ages of Strife and disable notifications for your account.";
	
				AgesOfStrifeServer.log.debug( "Message to send: " + message + "\nSubject: " + subject + "\nTo: " + email );
				try {
					InternetAddress internetAddress = new InternetAddress( parent.getMailSender() );
					mimeMessage.setFrom( internetAddress );
					mimeMessage.setSubject( subject );
					MimeMultipart mimeMultipart = new MimeMultipart();
					
					MimeBodyPart mimeBodyPart = new MimeBodyPart();
					mimeBodyPart.setText( message );
					mimeMultipart.addBodyPart( mimeBodyPart );
					mimeMessage.setContent( mimeMultipart );
					mimeMessage.setSentDate( new Date() );
					
					InternetAddress[] sendTo = new InternetAddress[1];
					sendTo[0] = new InternetAddress( email );
					
					Transport.send( mimeMessage, sendTo );
				} catch ( AddressException addressException ) {
					AgesOfStrifeServer.log.error( "Invalid e-mail address", addressException );
				} catch ( MessagingException messagingException ) {
					AgesOfStrifeServer.log.error( "Problem sending reminder message", messagingException );
				}
			}
		}
	}

	public Connection getConnection() throws ClassNotFoundException, SQLException {
		Class.forName( "com.mysql.jdbc.Driver" );
		String url = "jdbc:mysql://" + parent.getDatabaseLocation()
				+ ":" + parent.getDatabasePort() + "/" + parent.getDatabaseName() + "?jdbcCompliantTruncation=false";
		return DriverManager.getConnection( url, parent.getDatabaseUser(), parent.getDatabasePassword() );
	}
	
	private void updateRuler( int ruler_id ) {
		AgesOfStrifeServer.log.debug( "updating ruler with ruler_id: " + ruler_id );
		try {
			stmtUpdate.execute( "DELETE FROM army_visible WHERE ruler_id = " + ruler_id );
			rs = stmt.executeQuery( "SELECT farm_support, coal_support, iron_support, housing_support, draft " +
					"FROM faction " +
					"JOIN faction_member ON faction.faction_id = faction_member.faction_id " +
					"WHERE ruler_id = " + ruler_id + " AND invited = 0 AND requested = 0" );
			int food_support = 0;
			int coal_support = 0;
			int iron_support = 0;
			int housing_support = 0;
			int draft = 0;
			if( rs.next() ) {
				food_support = rs.getInt( "farm_support" );
				coal_support = rs.getInt( "coal_support" );
				iron_support = rs.getInt( "iron_support" );
				housing_support = rs.getInt( "housing_support" );
				draft = rs.getInt( "draft" );
			}
			
			rs = stmt.executeQuery( "SELECT premium " +
					"FROM users " +
					"JOIN ruler ON ruler.user_id = users.user_id " +
					"WHERE ruler_id = " + ruler_id );
			int premium = -1;
			if( rs.next() ) {
				premium = rs.getInt( "premium" );
			}

			rs = stmt.executeQuery( "SELECT * " +
					"FROM ruler " +
					"WHERE ruler_id = " + ruler_id );
			rs.next();
			int tax_level = rs.getInt( "tax_level" );
			int gold = rs.getInt( "gold" );
			int coal = rs.getInt( "coal" );
			int iron = rs.getInt( "iron" );
			int food = rs.getInt( "food" );
			boolean foodPriority;
			if( food == 0 && season != 0 ) {
				foodPriority = true;
				newsItem.clear();
				newsItem.addTitleText( "Food critically low" , true );
				newsItem.addText( "Since we are out of food our population has put all efforts into farming for the day." , true );
				newsItem.addText( "\n" , false );
				newsItem.addText( "No mining will be done. Try to see if enough workers are assigned to farming." , true );
				newsItem.addText( "\n\n" , false );
				newsItem.addText( "More information about food priority can be found" , true );
				newsItem.addText( " <a href=\"../aosmanual/concepts.php#Food priority\">" , false );
				newsItem.addText( "here" , true );
				newsItem.addText( "</a>." , false );
				newsItem.insert( ruler_id, 2, turn, date );
			}
			else {
				foodPriority = false;
			}
			
			int foodBefore = food;
			long year_gold = rs.getLong( "year_gold" );
			long year_iron = rs.getLong( "year_iron" );
			long year_coal = rs.getLong( "year_coal" );
			int recruits = rs.getInt( "recruits" );
			double morale = rs.getDouble( "morale" );
			// Calculate the score for units in the reserves
			long score = rs.getInt( "scouts" ) * 16l + rs.getInt( "infantry" ) * 24l + rs.getInt( "cavalry" ) * 128l + rs.getInt( "artillery" ) * 200l; 
			
			// Units remain in reserves or army until added, transfer is only administrative now and doesn't hold any units
			/*rs2 = stmt2.executeQuery( "SELECT SUM( scouts ), SUM( infantry ), SUM( cavalry ), SUM( artillery ) " +
					"FROM transfer " +
					"WHERE ruler_id = " + ruler_id );
			if( rs2.next() ) {
				score += rs2.getInt( 1 ) * 16l + rs2.getInt( 2 ) * 24l + rs2.getInt( 3 ) * 128l + rs2.getInt( 4 ) * 200l;
			}*/
			
			int total_coal_income = 0;
			int total_iron_income = 0;
			int tax_income = 0;
			double resourceMultiplier = 1;
			//AgesOfStrifeServer.log.debug( "Score for current ruler: " + score );
			
			// update villages
			rs = stmt.executeQuery( "SELECT * " +
					"FROM village " +
					"WHERE ruler_id = " + ruler_id );
			while ( rs.next() ) {
				int population = rs.getInt( "population" );
				int maxPopulation = rs.getInt( "max_population" );
				int village_id = rs.getInt( "village_id" ); 
				String village_name = rs.getString( "name" );
				int space = rs.getInt( "space" );
				int automatic = rs.getInt( "automatic" );
				String focus = rs.getString( "focus" );
				int preferedIronJobs = rs.getInt( "iron_jobs_prefered" );
				int preferedCoalJobs = rs.getInt( "coal_jobs_prefered" );
				int preferedFoodJobs = rs.getInt( "food_jobs_prefered" );
				int sendWorkersTo = rs.getInt( "send_workers_to" );
				int sendWorkersAmount = rs.getInt( "send_workers_amount" );

				rs2 = stmt2.executeQuery( "SELECT building_id, ammount " +
						"FROM village_buildings " +
						"WHERE village_id = " + village_id ); 
				double growth = 0;
				int coal_income = 0;
				int iron_income = 0;
				int food_income = 0;
				int jobs = 0;
				int spaceUsed = 0;
				int houses = 0;
				
				int otherJobs = 0;
				int maxIronJobs = 0;
				int maxCoalJobs = 0;
				int maxFoodJobs = 0;
				
				double houseMultiplier = 1;
				double coal_multiply = 1;
				double iron_multiply = 1;
				double food_multiply = 1;

				if( housing_support == 1 ) {
					houseMultiplier += 0.1;
				}
				
				if( "houses".equals( focus ) ) {
					houseMultiplier += 0.1;
					coal_multiply -= 0.1;
					iron_multiply -= 0.1;
				}
				else if( "farming".equals( focus ) ) {
					food_multiply += 0.1;
					coal_multiply -= 0.1;
					iron_multiply -= 0.1;
				}
				else if( "coal".equals( focus ) ) {
					coal_multiply += 0.1;
					food_multiply -= 0.1;
					houseMultiplier -= 0.1;
				}
				else if( "iron".equals( focus ) ) {
					iron_multiply += 0.1;
					food_multiply -= 0.1;
					houseMultiplier -= 0.1;
				}
				
				while ( rs2.next() ) {
					int tmp_building_id = rs2.getInt( "building_id" );
					if( tmp_building_id == 29 ) { // Sewers
						houseMultiplier += 0.5;
					}
					int ammount = rs2.getInt( "ammount" );
					for( int i = 0; i < building_id.length; i ++ ) {
						if( building_id[i] == tmp_building_id ) {
							growth += building_growth[i] * ammount;
							spaceUsed += building_space[i] * ammount;
							if( building_coal_income[i] > 0 ) {
								maxCoalJobs += building_jobs[i] * ammount;
							}
							else if( building_iron_income[i] > 0 ) {
								maxIronJobs += building_jobs[i] * ammount;
							}
							else if( building_food_income[i] > 0 ) {
								maxFoodJobs += building_jobs[i] * ammount;
							}
							else {
								otherJobs += building_jobs[i] * ammount;
							}
							houses += building_housing[i] * ammount;
							break;
						}
					}
				}
				
				int addedPopulation = ( int ) ( population * growth );
				if( addedPopulation < 37 ) {
					addedPopulation = 37;
				}
				population += addedPopulation;
				
				houses = ( int ) ( houses * houseMultiplier );
				
				int taxPopulation;
				if( population > houses ) {
					taxPopulation = houses;
				}
				else {
					taxPopulation = population;
				}

				if( tax_level == 1 ) { 
					tax_income += ( int ) ( taxPopulation * 0.00100 );
					resourceMultiplier = 1.5;
				}
				else if( tax_level == 2 ) {
					tax_income += ( int ) ( taxPopulation * 0.00200 );
					resourceMultiplier = 1;
				}
				else {
					tax_income += ( int ) ( taxPopulation * 0.00400 );
					resourceMultiplier = 0.5;
				}

				// The workforce is 60% of the taxable population
				int workforce = ( int ) ( taxPopulation * 0.6 );
				int homeWorkforce = workforce;
				// Here we check if any workers are send to this village from another one
				// 50% of those will be available for us
				
				rs2 = stmt2.executeQuery( "SELECT SUM(send_workers_amount) " +
						"FROM village " +
						"WHERE ruler_id = " + ruler_id + " AND send_workers_to = " + village_id );
				if( rs2.next() ) {
					workforce += ( int ) ( rs2.getInt( 1 ) * 0.5 );
				}
				
				int availableWorkforce = workforce;
				
				int ironJobs = 0;
				int coalJobs = 0;
				int foodJobs = 0;

				boolean queued = false;
				int queue_count = -1;
				rs2 = stmt2.executeQuery( "SELECT count(*) " +
						"FROM village_queue " +
						"WHERE village_id = " + village_id ); 
				if( rs2.next() ) {
					queue_count = rs2.getInt( "count(*)" );
					if( queue_count > 0 ) {
						queued = true;
					}
				}
				
				//System.out.println( "availableWorkforce: " + availableWorkforce + ", otherJobs: " + otherJobs );

				// update village_queue
				rs2 = stmt2.executeQuery( "SELECT * " +
						"FROM village_queue " +
						"WHERE rank = 0 AND village_id = " + village_id ); 
				if( rs2.next() ) {
					int time = rs2.getInt( "time" );
					int village_queue_id = rs2.getInt( "village_queue_id" );
					int destroy = rs2.getInt( "destroy" );
					time --;
					if( time == 0 ) {
						int tmp_building_id = rs2.getInt( "building_id" );
						if( destroy == 0 ) {
							rs3 = stmt3.executeQuery( "SELECT ammount " +
									"FROM village_buildings " +
									"WHERE village_id = " + village_id + " AND building_id = " + tmp_building_id );
							if( rs3.next() ) {
								stmtUpdate.execute( "UPDATE village_buildings SET ammount = " + ( rs3.getInt( "ammount" ) + 1 ) + " WHERE village_id = " + village_id + " AND building_id = " + tmp_building_id );
							}
							else {
								stmtUpdate.execute( "INSERT INTO village_buildings ( village_id, building_id, ammount ) VALUES ( " + village_id + ", " + tmp_building_id + ", 1 )" );
							}
						}
						else { // building needs to be destroyed
							rs3 = stmt3.executeQuery( "SELECT ammount FROM village_buildings WHERE village_id = " + village_id + " AND building_id = " + tmp_building_id );
							if( rs3.next() ) {
								int count = rs3.getInt( "ammount" );
								if( count > 1 ) {
									stmtUpdate.execute( "UPDATE village_buildings SET ammount = " + ( count - 1 ) + " WHERE village_id = " + village_id + " AND building_id = " + tmp_building_id );
								}
								else {
									stmtUpdate.execute( "DELETE FROM village_buildings WHERE village_id = " + village_id + " AND building_id = " + tmp_building_id );
								}
								for( int i = 0; i < building_id.length; i ++ ) {
									if( building_id[i] == tmp_building_id ) {
										space += building_space[i]; 
									}
								}
							}
						}
						rs3 = stmt3.executeQuery( "SELECT * " +
								"FROM village_queue " +
								"WHERE village_id = " + village_id );
						while ( rs3.next() ) {
							int rank = rs3.getInt( "rank" );
							int tmp_time = rs3.getInt( "time" );
							tmp_building_id = rs3.getInt( "building_id" );
							int village_queue_id2 = rs3.getInt( "village_queue_id" );
							int destroy2 = rs3.getInt( "destroy" );
							int repeat = rs3.getInt( "repeat" );
							if( rank == 0 ) {
								if( repeat == 1 ) { 
									stmtUpdate.execute( "UPDATE village_queue " +
											"SET rank = " + ( queue_count  - 1 ) + ", time = -1 " +
											"WHERE village_queue_id = " + village_queue_id2 );
								}
								else {
									stmtUpdate.execute( "DELETE FROM village_queue WHERE village_queue_id = " + village_queue_id2 );
								}
							}
							else {
								rank --;
								if( rank == 0 ) {
									if( destroy2 == 1 ) {
										tmp_time = 1;
									}
									else {
										for( int i = 0; i < building_id.length; i ++ ) {
											if( building_id[i] == tmp_building_id ) {
												boolean required = false;
												boolean upgrade = false;
												if( building_requires[i] != -1 ) {
													rs4 = stmt4.executeQuery( "SELECT count(*) " +
															"FROM village_buildings " +
															"WHERE village_id = " + village_id + " AND building_id = " + building_requires[i] );
													if( rs4.next() && rs4.getInt( 1 ) > 0 )  {
														required = true;
													}
												}
												else {
													required = true;
												}
												if( building_upgrades[i] != -1 ) {
													rs4 = stmt4.executeQuery( "SELECT count(*) " +
															"FROM upgrade_status " +
															"WHERE ruler_id = " + ruler_id + " AND upgrade_id = " + building_upgrades[i] + " AND achieved = 1"  );
													if( rs4.next() && rs4.getInt( 1 ) > 0 )  {
														upgrade = true;
													}
												}
												else {
													upgrade = true;
												}

												rs4 = stmt4.executeQuery( "SELECT count(*) " +
														"FROM village_buildings WHERE " +
														"village_id = " + village_id + " AND building_id = " + building_id[i] );
												rs4.next();
												// Check all constraints
												if( gold >= building_gold_cost[i] 
												            && availableWorkforce >= otherJobs + building_construction_jobs[i] 
												            && space - building_space[i] >= 0 
															&& ( rs4.getInt( "count(*)" ) < building_allowed[i] || building_allowed[i] == -1 ) 
															&& required && upgrade ) {
													//System.out.println( "starting construction on: " + building_id[i] );
													tmp_time = building_time_cost[i];
													gold -= building_gold_cost[i];
													otherJobs += building_construction_jobs[i];
													space -= building_space[i];
													break;
												}
												else {
													tmp_time = -1;
													//rank = 1;
												}
											}
										}
									}
									stmtUpdate.execute( "UPDATE village_queue SET rank = " + rank + ", time = " + tmp_time + " WHERE village_queue_id = " + village_queue_id2 );
								}
								else {
									stmtUpdate.execute( "UPDATE village_queue SET rank = " + rank + " WHERE village_queue_id = " + village_queue_id2 );
								}
							}
						}
					}
					else if( time <= -1 ) {
						int tmp_building_id = rs2.getInt( "building_id" );
						int tmp_time = time;
						if( tmp_time < -1 ) {
							tmp_time = -1;
						}
						if( destroy == 1 ) {
							tmp_time = 1;
							rs4 = stmt4.executeQuery( "SELECT count(*) FROM village_buildings WHERE village_id = " + village_id + " AND building_id = " + tmp_building_id );
							rs4.next();
							if( rs4.getInt( "count(*)" ) > 0 ) {
								rs3 = stmt3.executeQuery( "SELECT ammount FROM village_buildings WHERE village_id = " + village_id + " AND building_id = " + tmp_building_id );
								if( rs3.next() ) {
									int count = rs3.getInt( "ammount" );
									if( count > 1 ) {
										stmtUpdate.execute( "UPDATE village_buildings SET ammount = " + ( count - 1 ) + " WHERE village_id = " + village_id + " AND building_id = " + tmp_building_id );
									}
									else {
										stmtUpdate.execute( "DELETE FROM village_buildings WHERE village_id = " + village_id + " AND building_id = " + tmp_building_id );
									}
									for( int i = 0; i < building_id.length; i ++ ) {
										if( building_id[i] == tmp_building_id ) {
											space += building_space[i]; 
										}
									}
								}
							}
							rs3 = stmt3.executeQuery( "SELECT rank, village_queue_id FROM village_queue WHERE village_id = " + village_id );
							while ( rs3.next() ) {
								int rank = rs3.getInt( "rank" );
								int village_queue_id2 = rs3.getInt( "village_queue_id" );
								if( rank == 0 ) {
									stmtUpdate.execute( "DELETE FROM village_queue WHERE village_queue_id = " + village_queue_id2 );
								}
								else {
									stmtUpdate.execute( "UPDATE village_queue SET rank = " + ( rank - 1 ) + " WHERE village_queue_id = " + village_queue_id2 );
								}
							}
						}
						else {
							for( int i = 0; i < building_id.length; i ++ ) {
								if( building_id[i] == tmp_building_id ) {
									boolean required = false;
									boolean upgrade = false;
									if( building_requires[i] != -1 ) {
										rs4 = stmt4.executeQuery( "SELECT count(*) " +
												"FROM village_buildings " +
												"WHERE village_id = " + village_id + " AND building_id = " + building_requires[i] );
										if( rs4.next() && rs4.getInt( 1 ) > 0 )  {
											required = true;
										}
									}
									else {
										required = true;
									}
									if( building_upgrades[i] != -1 ) {
										rs4 = stmt4.executeQuery( "SELECT count(*) " +
												"FROM upgrade_status " +
												"WHERE ruler_id = " + ruler_id + " AND upgrade_id = " + building_upgrades[i] + " AND achieved = 1"  );
										if( rs4.next() && rs4.getInt( 1 ) > 0 )  {
											upgrade = true;
										}
									}
									else {
										upgrade = true;
									}
									
									rs4 = stmt4.executeQuery( "SELECT count(*) FROM village_buildings WHERE village_id = " + village_id + " AND building_id = " + building_id[i] );
									rs4.next();
									//System.out.println( "gold: " + gold + " >= building cost: " + building_gold_cost[i] );
									//System.out.println( "availableWorkforce: " + availableWorkforce + " >= other jobs: " + otherJobs + " + building jobs: " + building_construction_jobs[i] );
									//System.out.println( "space: " + space + " >= building space: " + building_space[i] );
									//System.out.println( "amount allowed: " + building_allowed[i] + " , already constructued: " + rs4.getInt( "count(*)" ) );
									// Check if requirements are met 
									if( gold >= building_gold_cost[i] 
									    && availableWorkforce >= otherJobs + building_construction_jobs[i] 
									    && space - building_space[i] >= 0 
									    && ( ( rs4.getInt( "count(*)" ) < building_allowed[i] || building_allowed[i] == -1 ) 
									    && upgrade && required ) ) {

										tmp_time = building_time_cost[i] - 1;
										gold -= building_gold_cost[i];
										otherJobs += building_construction_jobs[i];
										space -= building_space[i];
										break;
									}
									else {
										tmp_time = -1;
									}
								}
							}
							stmtUpdate.execute( "UPDATE village_queue SET time = " + tmp_time + " WHERE village_queue_id = " + village_queue_id ); 
						}
					}
					else {
						for( int i = 0; i < building_id.length; i ++ ) {
							int buildingId = rs2.getInt( "building_id" );
							if( buildingId == building_id[i] ) {
								otherJobs += building_construction_jobs[i];
							}
						}
						stmtUpdate.execute( "UPDATE village_queue " +
								"SET time = " + time + " " +
								"WHERE village_queue_id = " + village_queue_id ); 
					}
				}
				
				if( queued ) {
					rs2 = stmt2.executeQuery( "SELECT count(*) " +
							"FROM village_queue " +
							"WHERE village_id = " + village_id ); 
					if( rs2.next() ) {
						if( rs2.getInt( "count(*)" ) == 0 ) {
							newsItem.clear();
							newsItem.addTitleText( village_name + " ", false );
							newsItem.addTitleText( "has completed all construction.", true );
							newsItem.addText( village_name + " ", false );
							newsItem.addText( "has finished constructing all buildings that were queued.", true );
							newsItem.addText( "\n", false );
							newsItem.addText( "They are awaiting new construction orders now.", true );
							newsItem.addText( "\n", false );
							newsItem.addText( "Click", true );
							newsItem.addText( " <a href=\"../villages/village.php?name=" + village_name + "\">", false );
							newsItem.addText( "here", true );
							newsItem.addText( "</a> ", false );
							newsItem.addText( "to give new construction orders.", true );
							newsItem.insert( ruler_id, 2, turn, date );
						}
					}
				}
				
				if( !foodPriority ) {
					availableWorkforce -= otherJobs;
					if( availableWorkforce < 0 ) {
						otherJobs += availableWorkforce;
						availableWorkforce = 0;
					}
				}
				if( premium < 1 && automatic == 1 ) {
					automatic = 0;
				}
				
				if( automatic == 0 ) {
					foodJobs = getJobs( availableWorkforce, foodPriority ? maxFoodJobs : preferedFoodJobs, maxFoodJobs );
					availableWorkforce -= foodJobs;
					
					if( !foodPriority ) {
						ironJobs = getJobs( availableWorkforce, preferedIronJobs, maxIronJobs );
						availableWorkforce -= ironJobs;
						
						coalJobs = getJobs( availableWorkforce, preferedCoalJobs, maxCoalJobs );
						availableWorkforce -= coalJobs;
					}
				}
				else {
					// In the winter farmers are unemployed, so more recruitment happens
					if( season == 0 ) {
						maxFoodJobs = 0;
					}
					if( focus == "coal" ) {
						if( !foodPriority ) {
							coalJobs = getJobs( availableWorkforce, maxCoalJobs, maxCoalJobs );
							availableWorkforce -= coalJobs;
							ironJobs = getJobs( availableWorkforce, maxIronJobs, maxIronJobs );
							availableWorkforce -= ironJobs;
						}
						foodJobs = getJobs( availableWorkforce, maxFoodJobs, maxFoodJobs );
						availableWorkforce -= foodJobs;
					}
					else if( focus == "iron" ) {
						if( !foodPriority ) {
							ironJobs = getJobs( availableWorkforce, maxIronJobs, maxIronJobs );
							availableWorkforce -= ironJobs;
							coalJobs = getJobs( availableWorkforce, maxCoalJobs, maxCoalJobs );
							availableWorkforce -= coalJobs;
						}
						foodJobs = getJobs( availableWorkforce, maxFoodJobs, maxFoodJobs );
						availableWorkforce -= foodJobs;
					}
					else {
						foodJobs = getJobs( availableWorkforce, maxFoodJobs, maxFoodJobs );
						availableWorkforce -= foodJobs;
						if( !foodPriority ) {
							ironJobs = getJobs( availableWorkforce, maxIronJobs, maxIronJobs );
							availableWorkforce -= ironJobs;
							coalJobs = getJobs( availableWorkforce, maxCoalJobs, maxCoalJobs );
							availableWorkforce -= coalJobs;
						}
					}
				}
				
				int availableHomeWorkforce = homeWorkforce;
				if( availableHomeWorkforce > availableWorkforce ) {
					availableHomeWorkforce = availableWorkforce;
				}
				
				rs2 = stmt2.executeQuery( "SELECT count(*) " +
						"FROM village_buildings " +
						"WHERE village_id = " + village_id + " AND building_id = 6" );
				int recr = 0;
				rs2.next();
				int recruitment_office = rs2.getInt( 1 );
				if( recruitment_office > 0 ) {
					if( draft == 1 ) {
						// Recruit very little among workers
						recr = ( int ) Math.round( ( workforce - availableHomeWorkforce ) * 0.0000060 );
						// Recruit a lot among unemployed
						recr = ( int ) Math.round( availableHomeWorkforce * 0.0030 );
					}
					else {
						// Recruit very little among workers
						recr = ( int ) Math.round( ( workforce - availableHomeWorkforce ) * 0.0000040 );
						// Recruit a lot among unemployed
						recr = ( int ) Math.round( availableHomeWorkforce * 0.0020 );
					}
				}
				
				coal_income = ( int ) ( ( coalJobs * 0.1 ) * ( 0.01 * rs.getInt( "coal_quality" ) ) );
				iron_income = ( int ) ( ( ironJobs * 0.0666666666 ) * ( 0.01 * rs.getInt( "iron_quality" ) ) );
				if( season == 2 ) {
					food_income = ( int ) ( ( foodJobs ) * ( 0.01 * rs.getInt( "food_quality" ) ) );
				}
				else if( season == 1 || season == 3 ) {
					food_income = ( int ) ( ( foodJobs * 0.5 ) * ( 0.01 * rs.getInt( "food_quality" ) ) );
				}
				else {
					food_income = 0;
				}

				// check for coal enhancer
				rs2 = stmt2.executeQuery( "SELECT count(*) " +
						"FROM village_buildings " +
						"WHERE village_id = " + village_id + " AND building_id = 19" );
				rs2.next();
				int coal_enhancer = rs2.getInt( 1 );
				if( coal_enhancer > 0 ) {
					coal_multiply += 0.5;
				}
				if( coal_support == 1 ) {
					coal_multiply += 0.1;
				}
				
				// check for iron enhancer
				rs2 = stmt2.executeQuery( "SELECT count(*) FROM village_buildings WHERE village_id = " + village_id + " AND building_id = 17" );
				rs2.next();
				int iron_enhancer = rs2.getInt( 1 );
				if( iron_enhancer > 0 ) {
					iron_multiply += 0.5;
				}
				if( iron_support == 1 ) {
					iron_multiply += 0.1;
				}

				// check for food enhancer
				rs2 = stmt2.executeQuery( "SELECT count(*) FROM village_buildings WHERE village_id = " + village_id + " AND building_id = 15" );
				rs2.next();
				int food_enhancer = rs2.getInt( 1 );
				if( food_enhancer > 0 ) {
					food_multiply += 0.5;
				}
				if( food_support == 1 ) {
					food_multiply += 0.1;
				}

				coal_income *= coal_multiply * resourceMultiplier;
				iron_income *= iron_multiply * resourceMultiplier;
				food_income *= food_multiply;
				
				if( morale <= 0.2 ) {
					recr = ( int ) Math.round( recr * 0.2 );
					coal_income = ( int ) Math.round( coal_income * 0.5 );
					iron_income = ( int ) Math.round( iron_income * 0.5 );
					food_income = ( int ) Math.round( food_income * 0.5 );
				}
				else if( morale <= 0.4 ) {
					recr = ( int ) Math.round( recr * 0.6 );
					coal_income = ( int ) Math.round( coal_income * 0.8 );
					iron_income = ( int ) Math.round( iron_income * 0.8 );
					food_income = ( int ) Math.round( food_income * 0.8 );
				}
				
				population -= recr;
				recruits += recr;
				
				coal += coal_income;
				iron += iron_income;
				food += food_income;
				
				total_coal_income += coal_income;
				total_iron_income += iron_income;
				
				if( population > maxPopulation ) {
					population = maxPopulation;
				}

				// Food consumption
				food -= ( int ) ( population * 0.1 );
				
				if( food < 0 ) {
					// 6% of unfed population dies
					population += food * 0.6;
					food = 0;
				}
				
				// Population is not allowed to be below 1,000
				if( population < 1000 ) {
					population = 1000;
				}
				
				jobs = otherJobs + foodJobs + coalJobs + ironJobs;
				int unemployed = workforce - jobs;
				
				if( sendWorkersAmount > 0 && sendWorkersTo != -1 ) {
					rs2 = stmt2.executeQuery( "SELECT count(*) " +
							"FROM village " +
							"WHERE village_id = " + sendWorkersTo + " AND ruler_id = " + ruler_id );
					if( rs2.next() && rs2.getInt( 1 ) > 0 ) {
						if( sendWorkersAmount > unemployed ) {
							sendWorkersAmount = unemployed;
						}
					}
					else {
						sendWorkersAmount = 0;
						sendWorkersTo = -1;
					}
					jobs += sendWorkersAmount;
				}
				
				score += ( long) ( population * 4l + jobs * 2l );
				stmtUpdate.executeUpdate( "UPDATE village " +
						"SET population = " + population + ", jobs = " + jobs + ", workforce = " + workforce + ", " +
								"space = " + space + ", coal_income = " + coal_income + ", food_income = " + food_income + ", " +
								"iron_income = " + iron_income + ", food_jobs = " + foodJobs + ", coal_jobs = " + coalJobs + ", iron_jobs = " + ironJobs + "," +
								"send_workers_to = " + sendWorkersTo + ", send_workers_amount = " + sendWorkersAmount + " " +
						"WHERE village_id = " + village_id );

				// Update village building score
				rs2 = stmt2.executeQuery( "SELECT SUM( ammount * gold_cost * 25 ) " +
						"FROM village_buildings " +
						"JOIN buildings ON village_buildings.building_id = buildings.building_id " +
						"WHERE village_id = " + village_id );
				if( rs2.next() ) {
					score += rs2.getLong( 1 );
				}
			}

			gold += tax_income;
			year_gold += tax_income;
			year_coal += total_coal_income;
			year_iron += total_iron_income;
			
			//AgesOfStrifeServer.log.debug( "Score for current ruler: " + score );
			score = updateArmies( ruler_id, score );
			//AgesOfStrifeServer.log.debug( "Score for current ruler: " + score );
			score = handleTransfer( ruler_id, score );
			//AgesOfStrifeServer.log.debug( "Score for current ruler: " + score );
			// update officers
			int officer_pay = 0;
			rs = stmt.executeQuery( "SELECT rank FROM officers WHERE ruler_id = " + ruler_id );
			while ( rs.next() ) {
				int rank = rs.getInt( "rank" );
				officer_pay += 2 + ( rank * 3 );
			}
			
			gold -= officer_pay;

			gold = updateUpgrade( ruler_id, gold );

			// Get score from upgrades underway and achieved
			rs = stmt.executeQuery( "SELECT SUM(gold_cost * 50) " +
					"FROM upgrade_status " +
					"JOIN upgrades ON upgrade_status.upgrade_id = upgrades.upgrade_id " +
					"WHERE ruler_id = " + ruler_id + " AND ( achieved = 1 OR ( achieved = 0 AND time > 0 ) ) " );
			if ( rs.next() ) {
				score += rs.getLong( 1 );
			}
			
			// Get score from scouted villages
			rs = stmt.executeQuery( "SELECT count(*) " +
					"FROM scouted " +
					"WHERE ruler_id = " + ruler_id );
			if ( rs.next() ) {
				score += ( 1000l * rs.getLong( 1 ) );
			}
			
			// Adjust score for overall values
			score += ( long) ( gold * 5l + coal * 2l + iron * 3l + ( long) recruits + ( long) food );
			AgesOfStrifeServer.log.debug( "Score for current ruler: " + score );
			
			if( score < 0 ) {
				score = 0;
			}
			
			int foodIncome = food - foodBefore;
			
			stmtUpdate.executeUpdate( "UPDATE ruler " +
					"SET gold = " + gold + ", coal = " + coal + ", iron = " + iron + ", " +
					"recruits = " + recruits + ", score = " + score + ", lastday_taxes = " + tax_income + ", " +
					"officer_pay = " + officer_pay + ", coal_income = " + total_coal_income + ", iron_income = " + total_iron_income + "" +
					", year_gold = " + year_gold + ", year_iron = " + year_iron + ", year_coal = " + year_coal + ", " +
					"food = " + food + ", food_income = " + foodIncome + " " +
					"WHERE ruler_id = " + ruler_id );

			// Create auto trades
			if( turn % 3 == 0 ) {
				createAutoTrades( ruler_id, ( premium > 0 ) );
			}
		} catch ( Exception e ) {
			AgesOfStrifeServer.log.error( getStackError( e ) );
			e.printStackTrace();
		}
	}
	
	private void createAutoTrades( int rulerId, boolean hasPremium ) throws SQLException {
		AgesOfStrifeServer.log.debug( "Going through enabled auto trades for " + rulerId );
		rs = stmt.executeQuery( "SELECT gold, iron, coal, food " +
				"FROM ruler " +
				"WHERE `ruler_id` = " + rulerId );
		rs.next();
		int gold = rs.getInt( "gold" );
		int iron = rs.getInt( "iron" );
		int coal = rs.getInt( "coal" );
		int food = rs.getInt( "food" );
		int previousAdded = 0;
		
		rs = stmt.executeQuery( "SELECT * " +
				"FROM auto_trade " +
				"WHERE `ruler_id` = " + rulerId + " AND `enabled` = 1" );
		while( rs.next() ) {
			String resourceRequested = rs.getString( "resource_requested" );
			String resourceOffered = rs.getString( "resource_offered" );
			int tradeOver = rs.getInt( "trade_over" );
			int tradeBelow = rs.getInt( "trade_below" );
			int amount = rs.getInt( "amount" );
			int pricing = rs.getInt( "pricing" );
			int below = rs.getInt( "below" );
			int restValue = 0;
			double offerValue = 0;
			double requestValue = 0;
			AgesOfStrifeServer.log.debug( "resource requested: " + resourceRequested + ", resourceOffered " + resourceOffered + " and below: " + below );
			
			if( below == 1 ) {
				// We have to check if the current amount of our resource is below a certain value
				// if so we create trade offers requesting the resource
				if( "gold".equals( resourceRequested ) ) {
					rs2 = stmt2.executeQuery( "SELECT SUM(gold_want) " +
							"FROM trade " +
							"WHERE ruler_id = " + rulerId + " AND completed = 0 AND expired = 0" );
				}
				else if( "iron".equals( resourceRequested ) ) {
					rs2 = stmt2.executeQuery( "SELECT SUM(iron_want) " +
							"FROM trade " +
							"WHERE ruler_id = " + rulerId + " AND completed = 0 AND expired = 0" );
				}
				else if( "coal".equals( resourceRequested ) ) {
					rs2 = stmt2.executeQuery( "SELECT SUM(coal_want) " +
							"FROM trade " +
							"WHERE ruler_id = " + rulerId + " AND completed = 0 AND expired = 0" );
				}
				else if( "food".equals( resourceRequested ) ) {
					rs2 = stmt2.executeQuery( "SELECT SUM(food_want) " +
							"FROM trade " +
							"WHERE ruler_id = " + rulerId + " AND completed = 0 AND expired = 0" );
				}
				rs2.next();
				int added = rs2.getInt( 1 );
				AgesOfStrifeServer.log.debug( "added value from trades: " + added );
				
				int amountRequested = amount;
				if( pricing == 0 ) {
					amountRequested = ( int ) ( 1.15 * amount );
				}
				else if( pricing == 1 ) {
					amountRequested = ( int ) ( 1.05 * amount );
				}
				else if( pricing == 3 ) {
					amountRequested = ( int ) ( 0.95 * amount );
				}
				else if( pricing == 4 ) {
					amountRequested = ( int ) ( 0.85 * amount );
				}
				String requestSQL = "";
				if( "gold".equals( resourceRequested ) && gold + added < tradeBelow ) {
					restValue = tradeBelow - ( gold + added );
					requestValue = amountRequested;
					offerValue = amount;
					requestSQL = ( int ) ( requestValue ) + ", 0, 0, 0";
				}
				else if( "iron".equals( resourceRequested ) && iron + added < tradeBelow ) {
					restValue = tradeBelow - ( iron + added );
					requestValue = amountRequested;
					offerValue = amount * 0.4;
					requestSQL = "0, " + ( int ) ( requestValue ) + ", 0, 0";
				}
				else if( "coal".equals( resourceRequested ) && coal + added < tradeBelow ) {
					restValue = tradeBelow - ( coal + added );
					requestValue = amountRequested;
					offerValue = amount * 0.2;
					requestSQL = "0, 0, " + ( int ) ( requestValue ) + ", 0";
				}
				else if( "food".equals( resourceRequested ) && food + added < tradeBelow ) {
					restValue = tradeBelow - ( food + added );
					requestValue = amountRequested;
					offerValue = amount * 0.1;
					requestSQL = "0, 0, 0, " + ( int ) ( requestValue );
				}
				
				if( restValue + amount > 0 ) {
					int total = ( int ) Math.floor( restValue / amount );
					if( hasPremium && total + previousAdded > 9 ) {
						total = 9 - previousAdded;
					}
					else if( !hasPremium && total + previousAdded > 3 ) {
						total = 3 - previousAdded;
					}
					AgesOfStrifeServer.log.debug( "total trades to be created: " + total );
					
					if( total < 0 ) {
						total = 0;
					}
					previousAdded += total;
					
					String offerSQL = "";
					int offerAmount = 0;
					
					if( "gold".equals( resourceOffered ) ) {
						offerAmount = ( int ) offerValue;
						offerSQL =  offerAmount + ", 0, 0, 0";
					}
					else if( "iron".equals( resourceOffered ) ) {
						offerAmount = ( int ) ( offerValue * 2.5 );
						offerSQL = "0, " + offerAmount + ", 0, 0";
					}
					else if( "coal".equals( resourceOffered ) ) {
						offerAmount = ( int ) ( offerValue * 5 );
						offerSQL = "0, 0, " + offerAmount + ", 0";
					}
					else if( "food".equals( resourceOffered ) ) {
						offerAmount = ( int ) ( offerValue * 10 );
						offerSQL = "0, 0, 0, " + offerAmount;
					}
					
					for( int i = 0; i < total; i ++ ) {
						boolean enough = false;
						if( "gold".equals( resourceOffered ) && gold >= offerAmount ) {
							enough = true;
							gold -= offerAmount;
						}
						else if( "iron".equals( resourceOffered ) && iron >= offerAmount ) {
							enough = true;
							iron -= offerAmount;
						}
						else if( "coal".equals( resourceOffered ) && coal >= offerAmount ) {
							enough = true;
							coal -= offerAmount;
						}
						else if( "food".equals( resourceOffered ) && food >= offerAmount ) {
							enough = true;
							food -= offerAmount;
						}
						
						if( enough ) {
							AgesOfStrifeServer.log.debug( "Inserting auto trade" );
							stmtUpdate.execute( "INSERT INTO trade " +
									"( `gold_offer`, `iron_offer`, `coal_offer`, `food_offer`, `gold_want`, `iron_want`, `coal_want`, `food_want`, `ruler_id`, `turn`, `date`, `time` ) " +
									"VALUES( " + offerSQL + ", " + requestSQL + ", " + rulerId + ", " + turn + ", '" + date + "', 24 )" );
						}
					}
				}
			}
			else {
				// We have to check if the current amount of our resource is above a certain value
				// if so we create trade offers offering the resource
				int amountRequested = amount;
				if( pricing == 0 ) {
					amountRequested = ( int ) ( 0.85 * amount );
				}
				else if( pricing == 1 ) {
					amountRequested = ( int ) ( 0.95 * amount );
				}
				else if( pricing == 3 ) {
					amountRequested = ( int ) ( 1.05 * amount );
				}
				else if( pricing == 4 ) {
					amountRequested = ( int ) ( 1.15 * amount );
				}
				String offerSQL = "";
				if( "gold".equals( resourceOffered ) && gold > tradeOver ) {
					restValue = gold - tradeOver;
					requestValue = amountRequested;
					offerValue = amount;
					offerSQL = ( int ) ( offerValue ) + ", 0, 0, 0";
				}
				else if( "iron".equals( resourceOffered ) && iron > tradeOver ) {
					restValue = iron - tradeOver;
					requestValue = amountRequested * 0.4;
					offerValue = amount;
					offerSQL = "0, " + ( int ) ( offerValue ) + ", 0, 0";
				}
				else if( "coal".equals( resourceOffered ) && coal > tradeOver ) {
					restValue = coal - tradeOver;
					requestValue = amountRequested * 0.2;
					offerValue = amount;
					offerSQL = "0, 0, " + ( int ) ( offerValue ) + ", 0";
				}
				else if( "food".equals( resourceOffered ) && food > tradeOver ) {
					restValue = food - tradeOver;
					requestValue = amountRequested * 0.1;
					offerValue = amount;
					offerSQL = "0, 0, 0, " + ( int ) ( offerValue );
				}
				
				if( restValue > amount ) {
					int total = ( int ) Math.floor( restValue / amount );
					if( hasPremium && total > 9 ) {
						total = 9;
					}
					else if( !hasPremium && total > 3 ) {
						total = 3;
					}
					AgesOfStrifeServer.log.debug( "total trades to be created: " + total );
					
					String requestSQL = "";
					
					if( "gold".equals( resourceRequested ) ) {
						requestSQL = ( int ) ( requestValue ) + ", 0, 0, 0";
					}
					else if( "iron".equals( resourceRequested ) ) {
						requestSQL = "0, " + ( int ) ( requestValue * 2.5 ) + ", 0, 0";
					}
					else if( "coal".equals( resourceRequested ) ) {
						requestSQL = "0, 0, " + ( int ) ( requestValue * 5 ) + ", 0";
					}
					else if( "food".equals( resourceRequested ) ) {
						requestSQL = "0, 0, 0, " + ( int ) ( requestValue * 10 );
					}
					
					for( int i = 0; i < total; i ++ ) {
						boolean enough = false;
						if( "gold".equals( resourceOffered ) && gold >= amount ) {
							enough = true;
							gold -= amount;
						}
						else if( "iron".equals( resourceOffered ) && iron >= amount ) {
							enough = true;
							iron -= amount;
						}
						else if( "coal".equals( resourceOffered ) && coal >= amount ) {
							enough = true;
							coal -= amount;
						}
						else if( "food".equals( resourceOffered ) && food >= amount ) {
							enough = true;
							food -= amount;
						}
						
						if( enough ) {
							AgesOfStrifeServer.log.debug( "Inserting auto trade" );
							stmtUpdate.execute( "INSERT INTO trade " +
									"( `gold_offer`, `iron_offer`, `coal_offer`, `food_offer`, `gold_want`, `iron_want`, `coal_want`, `food_want`, `ruler_id`, `turn`, `date`, `time` ) " +
									"VALUES( " + offerSQL + ", " + requestSQL + ", " + rulerId + ", " + turn + ", '" + date + "', 24 )" );
						}
					}
				}
			}
		}
		
		stmtUpdate.execute( "UPDATE ruler " +
				"SET gold = " + gold + ", iron = " + iron + ", coal = " + coal + ", food = " + food + " " +
				"WHERE ruler_id = " + rulerId );
	}

	private int getJobs( int availableWorkers, int preferedJobs, int maxJobs ) {
		if( preferedJobs > maxJobs ) {
			preferedJobs = maxJobs;
		}
		
		if( preferedJobs > availableWorkers ) {
			preferedJobs = availableWorkers;
		}
		return preferedJobs;
	}
	
	private int updateUpgrade( int ruler_id, int gold ) throws SQLException {
		// update upgrades
		rs = stmt.executeQuery( "SELECT upgrades.upgrade_id, rank, time, upgrade_status_id, level, max_level " +
				"FROM upgrade_status " +
				"JOIN upgrades ON upgrades.upgrade_id = upgrade_status.upgrade_id " +
				"WHERE ruler_id = " + ruler_id + " AND achieved = 0 AND rank <= 0" );
		if ( rs.next() ) {
			int upgrade_id = rs.getInt( "upgrade_id" );
			int id = rs.getInt( "upgrade_status_id" );
			int time = rs.getInt( "time" );
			int max_level2 = rs.getInt( "max_level" );
			time --;
			boolean completed = false;
			if( time == 0 ) {
				stmtUpdate.execute( "UPDATE upgrade_status SET time = -1, achieved = 1, rank = -1 WHERE upgrade_status_id = " + id );
				completed = true;
				
				// Completed an upgrade: let's see how many are already done, maybe we need to set the discount turn
				rs2 = stmt2.executeQuery( "SELECT count(*) " +
						"FROM upgrade_status " +
						"WHERE upgrade_id = " + upgrade_id + " AND achieved = 1 AND level = " + max_level2 );
				/*System.out.println( "Query: SELECT count(*) " +
						"FROM upgrade_status " +
						"WHERE upgrade_id = " + upgrade_id + " AND achieved = 1 AND level = " + max_level2 );*/
				if( rs2.next() && rs2.getInt( 1 ) > 40 ) { 
					rs2 = stmt2.executeQuery( "SELECT count(*) " +
							"FROM upgrades " +
							"WHERE upgrade_id = " + upgrade_id + " AND discount_turn = -1" );
					if( rs2.next() && rs2.getInt( 1 ) == 1 ) {
						int discountCountdown = 48;
						int discountTurn = turn + discountCountdown;
						calendar.set( 1796, 01, 01 );
						calendar.add( GregorianCalendar.HOUR, discountTurn * 24 );
						String day = "" + calendar.get( GregorianCalendar.DAY_OF_MONTH );
						String month = "" + ( calendar.get( GregorianCalendar.MONTH ) + 1 );
						
						if( day.length() == 1 ) {
							day = "0" + day;
						}
						if( month.length() == 1 ) {
							month = "0" + month;
						}
						
						String discountDate = day + "-" + month + "-" + calendar.get( GregorianCalendar.YEAR );
						stmtUpdate.execute( "UPDATE upgrades " +
								"SET discount_turn = " + discountTurn + ", " +
								"discount_date = '" + discountDate + "' WHERE upgrade_id = " + upgrade_id );
					}
				}
				
			}
			
			if( time <= -2 || completed ) {
				rs3 = stmt3.executeQuery( "SELECT rank, upgrade_id, time, upgrade_status_id, level FROM upgrade_status WHERE achieved = 0 AND ruler_id = " + ruler_id );
				while ( rs3.next() ) {
					int rank = rs3.getInt( "rank" );
					id = rs3.getInt( "upgrade_status_id" );
					int tmp_time = rs3.getInt( "time" );
					int level = rs3.getInt( "level" );
					int tmp_gold = 0;
					upgrade_id = rs3.getInt( "upgrade_id" );
					if( completed ) {
						rank --;
					}
					if( rank <= 0 ) {
						rs4 = stmt4.executeQuery( "SELECT * " +
								"FROM upgrades " +
								"WHERE upgrade_id = " + upgrade_id );
						rs4.next();
						int time_cost = rs4.getInt( "time_cost" );
						int gold_cost = rs4.getInt( "gold_cost" );
						int requires = rs4.getInt( "requires" );
						int max_level = rs4.getInt( "max_level" );
						int gold_add = rs4.getInt( "gold_add" );
						int time_add = rs4.getInt( "time_add" );
						int discount_turn = rs4.getInt( "discount_turn" );
						if( discount_turn != -1 && turn > discount_turn ) {
							gold_cost = ( int ) Math.round( 0.25 * gold_cost );
							gold_add = ( int ) Math.round( 0.25 * gold_add );
							time_cost = ( int ) Math.round( 0.25 * time_cost );
							time_add = ( int ) Math.round( 0.25 * time_add );
						}
						int prereqs = 0;
						if( requires == -1 ) {
							prereqs = 1;
						}
						else { 
							rs4 = stmt4.executeQuery( "SELECT count(*) " +
									"FROM upgrade_status " +
									"WHERE upgrade_id = " + requires + " AND ruler_id = " + ruler_id + " AND achieved = 1" );
							rs4.next();
							prereqs = rs4.getInt( "count(*)" );
						}

						rs4 = stmt4.executeQuery( "SELECT count(*) FROM upgrade_status WHERE upgrade_id = " + upgrade_id + " AND ruler_id = " + ruler_id + " AND achieved = 1 AND level = " + level );
						rs4.next();
						
						//System.out.println( "prereqs: " + prereqs + "\r\ngold_cost = " + gold_cost + "\r\nalready have it: " + rs4.getInt( "count(*)" ) + "\r\ntime_cost: " + time_cost );
						
						if( level <= max_level && gold > gold_cost + gold_add * ( level - 1 ) && prereqs > 0 && rs4.getInt( "count(*)" ) == 0 ) {
							//System.out.println( "starting upgrade: " + upgrade_id );
							tmp_time = time_cost + time_add * ( level - 1 );
							if( !completed ) {
								tmp_time --;
							}
							tmp_gold = gold_cost + gold_add * ( level - 1 );
							gold -= tmp_gold;
						}
						else {
							tmp_time = -1;
						}
						stmtUpdate.execute( "UPDATE upgrade_status SET rank = " + rank + ", time = " + tmp_time + " WHERE upgrade_status_id = " + id );
					}
					else {
						stmtUpdate.execute( "UPDATE upgrade_status SET rank = " + rank + " WHERE upgrade_status_id = " + id );
					}
				}
			}
			else {
				stmtUpdate.execute( "UPDATE upgrade_status SET time = " + time + " WHERE upgrade_status_id = " + id );
			}
		}
		return gold;
	}
	
	private void resolveCombat() {
		try {
			HashMap<String, String> map = new HashMap<String, String>();
			rs = stmt.executeQuery( "SELECT * " +
					"FROM army " +
					"WHERE scout + infantry + cavalry + artillery > 0" );
			while ( rs.next() ) {
				//int army_id = rs.getInt( "army_id" );
				int x = ( int ) Math.round( rs.getDouble( "actual_x" ) );
				int y = ( int ) Math.round( rs.getDouble( "actual_y" ) );
				//System.out.println( "looking for enemy of army_id: " + army_id );
				if( map.get( "" + x + "," + y ) == null ) {
					//System.out.println( "marking army_id: " + army_id );
					map.put( "" + x + "," + y, "" );
					rs2 = stmt2.executeQuery( "SELECT village_id, name, ruler_id " +
							"FROM village " +
							"WHERE x = " + x + " AND y = " + y );
					String village = "";
					int village_owner_id = -1;
					int village_owner_faction_id = -1;
					int village_id = -1;
					if( rs2.next() ) {
						if( rs2.getString( "name" ) == null ) {
							village = "Independent village (" + x + ", " + y + ")";
						}
						else {
							village = rs2.getString( "name" ) + " (" + x + ", " + y + ")";
							village_owner_id = rs2.getInt( "ruler_id" );
							rs3 = stmt3.executeQuery( "SELECT faction_id " +
									"FROM faction_member " +
									"WHERE ruler_id = " + village_owner_id + " AND invited = 0 AND requested = 0"  );
							if( rs3.next() ) {
								village_owner_faction_id = rs3.getInt( "faction_id" );
							}
						}
						village_id = rs2.getInt( "village_id" );
					}
					else {
						village = "(" + x + ", " + y + ")";
					}
					rs2 = stmt2.executeQuery( "SELECT count(*) " +
							"FROM army " +
							"WHERE actual_x + 0.5 >= " + x + " AND actual_x - 0.5 < " + x + " AND actual_y + 0.5 >= " + y + " AND actual_y - 0.5 < " + y );
					rs2.next();
					int total = rs2.getInt( "count(*)" );
					if( total > 1 ) {
						//System.out.println( "found another army at same location" );
						int[] armies = new int[total];
						int[] alliedSize = new int[total];
						int[] arrived_turn = new int[total];
						int[] scout = new int[total];
						int[] infantry = new int[total];
						int[] cavalry = new int[total];
						int[] artillery = new int[total];
						int[] scoutBefore = new int[total];
						int[] infantryBefore = new int[total];
						int[] cavalryBefore = new int[total];
						int[] artilleryBefore = new int[total];
						int[] officer_id = new int[total];
						int[] ruler_id = new int[total];
						int[] faction_id = new int[total];
						int[] fortified = new int[total];
						long[] army_score = new long[total];
						double[] morale = new double[total];
						String[] name = new String[total];
						String[] rulerName = new String[total];
						String[] factionName = new String[total];

						rs2 = stmt2.executeQuery( "SELECT * " +
								"FROM army " +
								"WHERE actual_x + 0.5 >= " + x + " AND actual_x - 0.5 < " + x + " AND actual_y + 0.5 >= " + y + " AND actual_y - 0.5 < " + y +
								" ORDER BY RAND()" );
						int i = 0;
						int check = -2;
						boolean faction = false;
						boolean enemy = false;
						while ( rs2.next() ) {
							armies[i] = rs2.getInt( "army_id" );
							arrived_turn[i] = rs2.getInt( "arrived_turn" );
							scoutBefore[i] = scout[i] = rs2.getInt( "scout" );
							infantryBefore[i] = infantry[i] = rs2.getInt( "infantry" );
							cavalryBefore[i] = cavalry[i] = rs2.getInt( "cavalry" );
							artilleryBefore[i] = artillery[i] = rs2.getInt( "artillery" );
							army_score[i] = 32l * scout[i] + 48l * infantry[i] + 256l * cavalry[i] + 400l * artillery[i];
							alliedSize[i] = scout[i] + infantry[i] + cavalry[i] + artillery[i];
							officer_id[i] = rs2.getInt( "officer_id" );
							ruler_id[i] = rs2.getInt( "ruler_id" );
							fortified[i] = rs2.getInt( "fortified" );
							rs3 = stmt3.executeQuery( "SELECT faction.faction_id, name " +
									"FROM faction_member " +
									"JOIN faction ON faction.faction_id = faction_member.faction_id " +
									"WHERE ruler_id = " + ruler_id[i] + " AND requested = 0 AND invited = 0" );
							
							if( rs3.next() ) {
								faction_id[i] = rs3.getInt( "faction_id" );
								factionName[i] = rs3.getString( "name" );
								if( check == -2 ) {
									check = faction_id[i];
									faction = true;
								}
							}
							else { 
								faction_id[i] = -1;
								factionName[i] = "";
							}
							
							//AgesOfStrifeServer.log.debug( "faction_id: " + faction_id[i] );
							
							if( !faction && check == -2 ) {
								check = ruler_id[i];
							}
							if( ( faction && check != faction_id[i] ) || ( !faction && check != ruler_id[i] ) ) {
								enemy = true;
							}
							
							name[i] = rs2.getString( "name" );
							if( ruler_id[i] == -1 ) {
								rulerName[i] = "Independent forces";
								morale[i] = 1;
							}
							else {
								rs3 = stmt3.executeQuery( "SELECT name, morale " +
										"FROM ruler " +
										"WHERE ruler_id = " + ruler_id[i]  );
								rs3.next();
								rulerName[i] = rs3.getString( "name" );
								morale[i] = rs3.getDouble( "morale" );
							}
							i ++;
						}
						
						if( enemy ) {
							for( int p = 0; p < alliedSize.length; p ++ ) {
								boolean done = false;
								if( faction_id[p] == -1 ) {
									for( int q = 0; q < ruler_id.length; q ++ ) {
										if( !done ) {
											if( ruler_id[p] == ruler_id[q] && p > q ) {
												alliedSize[p] = alliedSize[q];
												done = true;
											}
											else if( ruler_id[p] == ruler_id[q] && p != q ) {
												alliedSize[p] += alliedSize[q];
											}
										}
									}
								}
								else {
									for( int q = 0; q < faction_id.length; q ++ ) {
										if( !done ) {
											if( faction_id[p] == faction_id[q] && p > q ) {
												alliedSize[p] = alliedSize[q];
												done = true;
											}
											else if( faction_id[p] == faction_id[q] && p != q ) {
												alliedSize[p] += alliedSize[q];
											}
										}
									}
								}
							}
							
							int[] effeciency = new int[armies.length];
							float[] attackInf = new float[armies.length];
							float[] attackCav = new float[armies.length];
							float[] attackArt = new float[armies.length];
							long[] experience = new long[armies.length];
							int[] devideBy = new int[armies.length];
							long[] total_enemy_score = new long[total];
							long[] xp_gained = new long[armies.length];
							//int[] enemies = new int[armies.length];
							float[] defenseBonus = new float[armies.length];
							float[] defenseBonusShow = new float[armies.length];
							float[] attackBonus = new float[armies.length];
							double[] riskBonus = new double[armies.length];
							String[] officerName = new String[armies.length];
							boolean[] empty = new boolean[armies.length];
							int[] killedScout = new int[armies.length];
							int[] killedInfantry = new int[armies.length];
							int[] killedCavalry = new int[armies.length];
							int[] killedArtillery = new int[armies.length];
							int[] lostScout = new int[armies.length];
							int[] lostInfantry = new int[armies.length];
							int[] lostCavalry = new int[armies.length];
							int[] lostArtillery = new int[armies.length];
							float[] attackEffeciencyInf = new float[total];
							float[] defenseEffeciencyInf = new float[total];
							float[] attackEffeciencyCav = new float[total];
							float[] defenseEffeciencyCav = new float[total];
							float[] attackEffeciencyArt = new float[total];
							float[] defenseEffeciencyArt = new float[total];
							float[] combinedArmySizeModifier = new float[total];
	
							for( int p = 0; p < armies.length; p ++ ) {
								devideBy[p] = 0;
								for( int q = 0; q < armies.length; q ++ ) {
									if( ( faction_id[p] == -1 && ruler_id[p] == ruler_id[q] ) || ( faction_id[p] != -1 && faction_id[p] == faction_id[q] ) ) {
										devideBy[p] ++;
										total_enemy_score[p] += army_score[q];
									}
								}
								attackBonus[p] = 1;
								defenseBonus[p] = 1;
								
								if( fortified[p] == 1 ) {
									defenseBonus[p] += 0.1;
								}
								
								if( morale[p] > 0.8 ) {
									defenseBonus[p] += 0.02;
									attackBonus[p] += 0.02;
								}
								
								if( village_owner_id == ruler_id[p] || ( faction_id[p] != -1 && faction_id[p] == village_owner_faction_id ) ) {
									double village_defense = 0;
									double village_offense = 0;
									rs3 = stmt3.executeQuery( "SELECT building_id " +
											"FROM village_buildings " +
											"WHERE village_id = " + village_id );
									while ( rs3.next() ) {
										int tmp_building_id = rs3.getInt( "building_id" );
										for( int w = 0; w < building_id.length; w ++ ) {
											if( building_id[w] == tmp_building_id ) {
												village_offense += building_offense_bonus[w];
												village_defense += building_defense_bonus[w];
												break;
											}
										}
									}
									
									double turns_here = turn - arrived_turn[p];
									if( turns_here > 4 ) {
										turns_here = 4;
									}
									if( turns_here < 0 ) {
										turns_here = 0;
									}
									turns_here *= 0.25;
									defenseBonus[p] += village_defense * turns_here; 
									attackBonus[p] += village_offense * turns_here;
								}
								
								if( faction_id[p] != -1 ) {
									rs3 = stmt3.executeQuery( "SELECT alert " +
											"FROM faction " +
											"WHERE faction_id = " + faction_id[p]  );
									if( rs3.next() && rs3.getInt( "alert" ) == 1 ) {
										attackBonus[p] += 0.05;
										defenseBonus[p] += 0.05;
									}
								}
								
								float infSize = ( float ) ( infantry[p] + scout[p] ) / ( float ) ( infantry[p] + scout[p] + cavalry[p] + artillery[p] );
								float cavSize = ( float ) ( cavalry[p] ) / ( float ) ( infantry[p] + scout[p] + cavalry[p] + artillery[p] );
								float artSize = ( float ) ( artillery[p] ) / ( float ) ( infantry[p] + scout[p] + cavalry[p] + artillery[p] );;
								attackEffeciencyInf[p] = 1f;
								defenseEffeciencyInf[p] = 1f;
								attackEffeciencyCav[p] = 1f;
								defenseEffeciencyCav[p] = 1f;
								attackEffeciencyArt[p] = 1f;
								defenseEffeciencyArt[p] = 1f;
								
								if( infSize < 0.5 ) {
									defenseEffeciencyInf[p] += ( 0.5f - infSize );
									attackEffeciencyInf[p] -= ( 0.5f - infSize );
								}
								
								if( cavSize < 0.10 ) {
									defenseEffeciencyCav[p] += cavSize;
									attackEffeciencyCav[p] -= ( cavSize * 2f );
								}
								else if( cavSize > 0.30 ) {
									defenseEffeciencyCav[p] += ( ( cavSize - 0.30f ) * 0.5f );
									attackEffeciencyCav[p] -= ( cavSize - 0.30f );
								}
								
								if( artSize < 0.05 ) {
									defenseEffeciencyArt[p] += artSize;
									attackEffeciencyArt[p] -= artSize;
								}
								else if( artSize > 0.15 ) {
									defenseEffeciencyArt[p] += ( artSize - 0.15f );
									attackEffeciencyArt[p] -= ( artSize - 0.15f );
								}
								
								combinedArmySizeModifier[p] = 1;
								float fightingNumber = 100000f;
								// max fighting size is determined by total size (penalty above 500k)
								if( alliedSize[p] > 500000 && alliedSize[p] < 4000000 ) {
									fightingNumber = 100000f - ( ( alliedSize[p] - 500000f ) * 0.025714285f );
								}
								else if( alliedSize[p] > 4000000 ) {
									fightingNumber = 10000f;
								}
								
								AgesOfStrifeServer.log.debug( "fightingNumber (" + name[p] + "): " + fightingNumber );
							
								
								// Combined allied armies above this number get a penalty
								if( alliedSize[p] > fightingNumber ) {
									combinedArmySizeModifier[p] = fightingNumber / alliedSize[p];
									if( combinedArmySizeModifier[p] < 0.00000001 ) {
										combinedArmySizeModifier[p] = 0.00000001f;
									}
								}
								
								attackInf[p] = ( ( int ) Math.round( scout[p] * 0.44444 + 	infantry[p] + 			cavalry[p] * 4 + 		artillery[p] * 11.1111 ) * attackBonus[p] * attackEffeciencyInf[p] * combinedArmySizeModifier[p] );    
								attackCav[p] = ( ( int ) Math.round( scout[p] * 0.11111 +	infantry[p] * 0.25 + 	cavalry[p] +			artillery[p] *  1.1719 ) * attackBonus[p] * attackEffeciencyCav[p] * combinedArmySizeModifier[p] );    
								attackArt[p] = ( ( int ) Math.round( scout[p] * 0.04 + 		infantry[p] * 0.09 + 	cavalry[p] * 0.853312 +	artillery[p] ) * attackBonus[p] * attackEffeciencyArt[p] * combinedArmySizeModifier[p] );
								AgesOfStrifeServer.log.debug( "Size penalty: " + combinedArmySizeModifier[p] );
								AgesOfStrifeServer.log.debug( "Cavalry efficiency: " + attackEffeciencyCav[p] );
								AgesOfStrifeServer.log.debug( "Attack power cavalry: " + attackCav[p] );
								
								if( scout[p] + infantry[p] + cavalry[p] + artillery[p] == 0 ) {
									empty[p] = true;
									AgesOfStrifeServer.log.debug( "Empty army in combat." );
								}
								else {
									empty[p] = false;
								}
								
								rs2 = stmt2.executeQuery( "SELECT name, experience, rank, offense, defense, risks " +
										"FROM officers " +
										"WHERE officer_id = " + officer_id[p]  );
								if( rs2.next() ) {
									attackBonus[p] += 0.02 * rs2.getInt( "offense" );
									defenseBonus[p] += 0.02 * rs2.getInt( "defense" );
									officerName[p] = rs2.getString( "name" );
									int rank = rs2.getInt( "rank" );
									if( rank == 0 ) {
										officerName[p] = "2nd lieutenant " + officerName[p];
									}
									else if( rank == 1 ) {
										officerName[p] = "1st lieutenant " + officerName[p];
									}
									else if( rank == 2 ) {
										officerName[p] = "captain " + officerName[p];
									}
									else if( rank == 3 ) {
										officerName[p] = "major " + officerName[p];
									}
									else if( rank == 4 ) {
										officerName[p] = "lieutenant-colonel " + officerName[p];
									}
									else if( rank == 5 ) {
										officerName[p] = "colonel " + officerName[p];
									}
									else if( rank == 6 ) {
										officerName[p] = "general " + officerName[p];
									}
									else if( rank == 7 ) {
										officerName[p] = "field marshal " + officerName[p];
									}
									experience[p] = rs2.getLong( "experience" );
									if( experience[p] > 50000000 ) {
										officerName[p] = "legendary " + officerName[p];
									}
									else if( experience[p] > 5000000 ) {
										officerName[p] = "famous " + officerName[p];
									}
									else if( experience[p] > 500000 ) {
										officerName[p] = "well known " + officerName[p];
									}
									effeciency[p] ++;
									
									double chance = 0;
									if( experience[p] >      50000000 ) {
										chance = 0.05;
									}
									else if( experience[p] > 25000000 ) {
										chance = 0.04;
									}
									else if( experience[p] > 12500000 ) {
										chance = 0.03;
									}
									else if( experience[p] >  6250000 ) {
										chance = 0.02;
									}
									else if( experience[p] >  3125000 ) {
										chance = 0.01;
									}
									
									if( rs2.getInt( "risks" ) == 0 ) {
										riskBonus[p] = chance;
									}
									else {
										chance = 0.5 * ( chance / ( rs2.getInt( "risks" ) * 0.1 ) );
										AgesOfStrifeServer.log.info( "Battle chance: " + ( chance + 0.5 ) );
										double random = Math.random();
										AgesOfStrifeServer.log.info( "Random value: " + random );
										if( random <= 0.5 + chance ) {
											riskBonus[p] = rs2.getInt( "risks" ) * 0.1;
										}
										else {
											riskBonus[p] = rs2.getInt( "risks" ) * -0.1;
										}
									}
									attackBonus[p] += riskBonus[p];
									defenseBonus[p] += riskBonus[p];
								}
								else {
									officerName[p] = "no one";
									experience[p] = 0;
									riskBonus[p] = 0;
								}
								AgesOfStrifeServer.log.debug( "Applied risk bonus: " + riskBonus[p] );
								
								defenseBonusShow[p] = defenseBonus[p];
								defenseBonus[p] = 1 / defenseBonus[p];
							}
							
							for( int p = 0; p < armies.length; p ++ ) {
								if( !empty[p] ) {
									for( int w = 0; w < armies.length; w ++ ) {
										if( ( faction_id[w] == -1 && ruler_id[w] != ruler_id[p] ) || ( faction_id[w] != -1 && faction_id[w] != faction_id[p] ) ) {//faction_id[w] != faction_id[p] ) {
											boolean turnOne = true;
											boolean allDead = false;
											double multiplier = ( double ) army_score[w] / total_enemy_score[w];
											//System.out.println( "army_score[w] = " + army_score[w] );
											//System.out.println( "total_enemy_score[w] = " + total_enemy_score[w] );
											//System.out.println( "( double ) army_score[w] / total_enemy_score[w] = " + ( ( double ) army_score[w] / total_enemy_score[w] ) );
											int attack = 0;
											int add = 0;
											int oldKilledScout = killedScout[p];
											int oldKilledInfantry = killedInfantry[p];
											int oldKilledCavalry = killedCavalry[p];
											int oldKilledArtillery = killedArtillery[p];
											
											// let all units do their damage
											while ( ( add > 0 || turnOne ) && !allDead ) {
												//System.out.println( "add = " + add );
												//System.out.println( "allDead = " + allDead );
												allDead = true;
												//double difference = ( ( ( double ) ( scout[w] + infantry[w] + cavalry[w] + artillery[w] ) ) / enemies[w] ) * 0.4 + 0.80;
												if( turnOne ) {
													attack = ( int ) ( 0.05 * defenseBonus[w] * defenseEffeciencyInf[w] * ( attackInf[p] /*+ effeciency[p]*/ ) );
													/*if( attack == 0 ) { 
														attack = 1;
													}*/
													//System.out.println( "attack = " + attack );
													//System.out.println( "attack * multiplier = " + ( int ) Math.round( attack * multiplier ) );
													attack = ( int ) Math.round( attack * multiplier );
												}
												else {
													attack = 0;
												}
												attack += add;
												
												if( scout[w] > 0 ) {
													lostScout[w] += scout[w];
													killedScout[p] += scout[w];
													scout[w] -= attack;
													if( scout[w] < 0 ) {
														//killedScout[p] += scout[w]; 
														//lostScout[w] += scout[w];
														add = scout[w];
														scout[w] = 0;
													}
													else {
														allDead = false;
														killedScout[p] -= scout[w];
														lostScout[w] -= scout[w];
														add = 0;
													}
												}
												else {
													//lostScout[w] = 0;
													//killedScout[p] = 0;
													add = attack;
												}
												xp_gained[w] += ( killedScout[p] - oldKilledScout ) * 16;
												xp_gained[p] += ( killedScout[p] - oldKilledScout ) * 32;
												if( turnOne ) {
													attack = ( int ) ( 0.05 * defenseBonus[w] * defenseEffeciencyInf[w] * ( attackInf[p] /*+ effeciency[p]*/ ) );
													/*if( attack == 0 ) { 
														attack = 1;
													}*/
													attack = ( int ) Math.round( attack * multiplier );
												}
												else {
													attack = 0;
												}
												attack += add;
												if( infantry[w] > 0 ) {
													killedInfantry[p] += infantry[w];
													lostInfantry[w] += infantry[w];
													infantry[w] -= attack;
													if( infantry[w] < 0 ) {
														//killedInfantry[p] += infantry[w];
														//lostInfantry[w] += infantry[w];
														add = - infantry[w];
														infantry[w] = 0;
														double rest = add / attackInf[p];
														add = ( int ) ( rest * attackCav[p] );
													}
													else {
														allDead = false;
														killedInfantry[p] -= infantry[w];
														lostInfantry[w] -= infantry[w];
														add = 0;
													}
												}
												else {
													//lostInfantry[w] -= killedInfantry[p];
													//killedInfantry[p] = 0;
													add = ( int ) ( ( attack / attackInf[p] ) * attackCav[p] );
												}
												xp_gained[w] += ( killedInfantry[p] - oldKilledInfantry )  * 24;
												xp_gained[p] += ( killedInfantry[p] - oldKilledInfantry ) * 48;
												if( turnOne ) {
													attack = ( int ) ( 0.1 * defenseBonus[w] * defenseEffeciencyCav[w] * ( attackCav[p] /*+ effeciency[p]*/ ) );
													/*if( attack == 0 ) {
														attack = 1;
													}*/
													attack = ( int ) Math.round( attack * multiplier );
												}
												else {
													attack = 0;
												}
												attack += add;
												if( cavalry[w] > 0 ) {
													killedCavalry[p] += cavalry[w];
													lostCavalry[w] += cavalry[w];
													cavalry[w] -= attack;
													if( cavalry[w] < 0 ) {
														//killedCavalry[p] += cavalry[w];
														//lostCavalry[w] += cavalry[w];
														add = - cavalry[w];
														cavalry[w] = 0;
														double rest = add / attackCav[p];
														add = ( int ) ( rest * attackArt[p] );
													}
													else {
														add = 0;
														allDead = false;
														killedCavalry[p] -= cavalry[w];
														lostCavalry[w] -= cavalry[w];
													}
												}
												else {
													//lostCavalry[w] -= killedCavalry[p];
													//killedCavalry[p] = 0;
													add = ( int ) ( ( attack / attackCav[p] ) * attackArt[p] );
												}
												xp_gained[w] += ( killedCavalry[p] - oldKilledCavalry ) * 128;
												xp_gained[p] += ( killedCavalry[p] - oldKilledCavalry ) * 256;
												if( turnOne ) {
													attack = ( int ) ( 0.1 * defenseBonus[w] * defenseEffeciencyArt[w] * ( attackArt[p] /*+ effeciency[p]*/ ) );
													/*if( attack == 0 ) {
														attack = 1;
													}*/
													attack = ( int ) Math.round( attack * multiplier );
												}
												else {
													attack = 0;
												}
												attack += add;
												if( artillery[w] > 0 ) {
													lostArtillery[w] += artillery[w];
													killedArtillery[p] += artillery[w];
													artillery[w] -= attack;
													if( artillery[w] < 0 ) {
														//killedArtillery[p] += artillery[w];
														//lostArtillery[w] += artillery[w];
														add = -artillery[w];
														artillery[w] = 0;
														//add *= 45;
														double rest = add / attackArt[p];
														add = ( int ) ( rest * attackInf[p] );
													}
													else {
														add = 0;
														allDead = false;
														killedArtillery[p] -= artillery[w];
														lostArtillery[w] -= artillery[w];
													}
												}
												else {
													//lostArtillery[w] -= killedArtillery[p];
													//killedArtillery[p] = 0;
													add = ( int ) ( ( attack / attackArt[p] ) * attackInf[p] );
												}
												xp_gained[w] += ( killedArtillery[p] - oldKilledArtillery ) * 200;
												xp_gained[p] += ( killedArtillery[p] - oldKilledArtillery ) * 400;
												
												if( turnOne ) {
													turnOne = false;
												}
											}
										}
									}
								}
							}
							
							long totalXP = 0;
							long killedTotal = 0;
							for( int p = 0; p < xp_gained.length; p ++  ) {
								totalXP += ( long ) xp_gained[p];
								killedTotal += ( long ) killedScout[p] + ( long ) killedInfantry[p] + ( long ) killedCavalry[p] + ( long ) killedArtillery[p]; 
							}
	
							newsItem.clear();
							for( int p = 0; p < armies.length; p ++ ) {
								if( !empty[p] ) {
									newsItem.addText( "\n" + name[p] + " ", false );
									newsItem.addText( "lead by", true );
									newsItem.addText( " " + officerName[p] + " ", false );
									newsItem.addText( "under command of", true );
									newsItem.addText( " " + rulerName[p], false );
									if( faction_id[p] != -1 ) {
										newsItem.addText( " ", false );
										newsItem.addText( "from", true );
										newsItem.addText( " " + factionName[p], false );
									}
									newsItem.addText( "\n", false );
									String modifier = "";
									if( riskBonus[p] > 0 ) {
										modifier = "+";
									}
									if( combinedArmySizeModifier[p] != 1 ) {
										newsItem.addText( "Army size penalty", true );
										newsItem.addText( ": <strong class=\"offense-bonus\">" + ( int ) Math.round( ( 1 - combinedArmySizeModifier[p] ) * 100 ) + "%</strong>", false );
										newsItem.addText( "\n", false );
									}
									if( attackBonus[p] != 1 ) {
										newsItem.addText( "Attack bonus", true );
										newsItem.addText( ": <strong class=\"offense-bonus\">" + ( int ) Math.round( ( ( attackBonus[p] - riskBonus[p] ) - 1 ) * 100 ) + "%</strong>", false );
										if( riskBonus[p] != 0 ) {
											newsItem.addText( " (<strong class=\"offense-bonus\">" + modifier + ( int ) Math.round( riskBonus[p] * 100 ) + "%</strong>)", false );
										}
										newsItem.addText( "\n", false );
									}
									if( defenseBonusShow[p] != 1 ) {
										newsItem.addText( "Defense bonus", true );
										newsItem.addText( ": <strong class=\"defense-bonus\">" + ( int ) Math.round( ( ( defenseBonusShow[p] - riskBonus[p] ) - 1 ) * 100 ) + "%</strong>", false );
										if( riskBonus[p] != 0 ) {
											newsItem.addText( " (<strong class=\"defense-bonus\">" + modifier + ( int ) Math.round( riskBonus[p] * 100 ) + "%</strong>)", false );
										}
										newsItem.addText( "\n", false );
									}
									if( scout[p] < 0 ) {
										scout[p] = 0;
									}
									newsItem.addText( "Experience gained", true );
									newsItem.addText( ": " + Utils.formatNumber( "" + xp_gained[p] ) + "\n", false );
									newsItem.addText( "<table class=\"news-table\"><tr><th>", false ); 
									newsItem.addText( "Units", true );
									newsItem.addText( "</th><th align=\"right\">", false );
									newsItem.addText( "Effectiveness", true );
									newsItem.addText( "</th><th align=\"right\">", false );
									newsItem.addText( "Before", true );
									newsItem.addText( "</th><th align=\"right\">", false );
									newsItem.addText( "After", true );
									newsItem.addText( "</th><th align=\"right\">", false );
									newsItem.addText( "Lost", true );
									newsItem.addText( "</th></tr>", false );
									newsItem.addText( "<tr><td>", false ); 
									int infEffectiveness = ( int ) Math.round( ( defenseEffeciencyInf[p] + attackEffeciencyInf[p] ) * 50f );
									newsItem.addText( "Scouts", true );
									newsItem.addText( "</td><td align=\"right\">" + ( scoutBefore[p] == 0 ? "-" : infEffectiveness + "%" ) + "</strong></td>", false );
									newsItem.addText( "<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + scoutBefore[p] ) + "</strong></td>", false );
									newsItem.addText( "<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + scout[p] ) + "</strong></td>", false );
									newsItem.addText( "<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + ( scoutBefore[p] - scout[p] ) ) + "</strong></td></tr>", false );
									if( infantry[p] < 0 ) {
										infantry[p] = 0;
									}
									
									newsItem.addText( "<tr class=\"even\"><td>", false ); 
									newsItem.addText( "Infantry", true );
									newsItem.addText( "</td><td align=\"right\">" + ( infantryBefore[p] == 0 ? "-" : infEffectiveness + "%" ) + "</strong></td>", false );
									newsItem.addText( "<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + infantryBefore[p] ) + "</strong></td>", false );
									newsItem.addText( "<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + infantry[p] ) + "</strong></td>", false );
									newsItem.addText( "<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + ( infantryBefore[p] - infantry[p] ) ) + "</strong></td></tr>", false );
									if( cavalry[p] < 0 ) {
										cavalry[p] = 0;
									}
									int cavEffectiveness = ( int ) Math.round( ( defenseEffeciencyCav[p] + attackEffeciencyCav[p] ) * 50f );
									newsItem.addText( "<tr><td>", false ); 
									newsItem.addText( "Cavalry", true );
									newsItem.addText( "</td><td align=\"right\">" + ( cavalryBefore[p] == 0 ? "-" : cavEffectiveness + "%" ) + "</strong></td>", false );
									newsItem.addText( "<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalryBefore[p] ) + "</strong></td>", false );
									newsItem.addText( "<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalry[p] ) + "</strong></td>", false );
									newsItem.addText( "<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + ( cavalryBefore[p] - cavalry[p] ) ) + "</strong></td></tr>", false );
									if( artillery[p] < 0 ) {
										artillery[p] = 0;
									}
									int artEffectiveness = ( int ) Math.round( ( defenseEffeciencyArt[p] + attackEffeciencyArt[p] ) * 50f );
									newsItem.addText( "<tr class=\"even\"><td>", false ); 
									newsItem.addText( "Artillery", true );
									newsItem.addText( "</td><td align=\"right\">" + ( artilleryBefore[p] == 0 ? "-" : artEffectiveness + "%" ) + "</strong></td>", false );
									newsItem.addText( "<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + artilleryBefore[p] ) + "</strong></td>", false );
									newsItem.addText( "<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + artillery[p] ) + "</strong></td>", false );
									newsItem.addText( "<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + ( artilleryBefore[p] - artillery[p] ) ) + "</strong></td></tr></table>", false );
								}
								int woundedScouts = ( int ) ( ( scoutBefore[p] - scout[p] ) * 0.4 );
								int woundedInfantry = ( int ) ( ( infantryBefore[p] - infantry[p] ) * 0.4 );
								int woundedCavalry = ( int ) ( ( cavalryBefore[p] - cavalry[p] ) * 0.4 );
								int woundedArtillery = ( int ) ( ( artilleryBefore[p] - artillery[p] ) * 0.4 );
								
								PreparedStatement preparedStatement = con.prepareStatement( "INSERT INTO transfer " +
										"( scouts, infantry, cavalry, artillery, complete_turn, ruler_id ) " +
										"VALUES( ?, ?, ?, ?, ?, ? )" );
								preparedStatement.setInt( 1, woundedScouts );
								preparedStatement.setInt( 2, woundedInfantry );
								preparedStatement.setInt( 3, woundedCavalry );
								preparedStatement.setInt( 4, woundedArtillery );
								preparedStatement.setInt( 5, turn + 24 );
								preparedStatement.setInt( 6, ruler_id[p] );
								preparedStatement.execute();
								
								stmtUpdate.execute( "UPDATE officers SET experience = " + ( experience[p] + xp_gained[p] ) + " WHERE officer_id = " + officer_id[p] );
								if( scout[p] + infantry[p] + cavalry[p] + artillery[p] == 0 ) {
									stmtUpdate.execute( "DELETE FROM army_orders WHERE army_id = " + armies[p] );
									stmtUpdate.execute( "DELETE FROM army WHERE army_id = " + armies[p] );
								}
								else {
									stmtUpdate.execute( "UPDATE army SET scout = " + scout[p] + ", infantry = " + infantry[p] + ", cavalry = " + cavalry[p] + ", artillery = " + artillery[p] + " WHERE army_id = " + armies[p] );
								}
							}
							int count = 0;
							for( int p = 0; p < ruler_id.length; p ++ ) {
								boolean same = empty[p];
								if( !same ) {
									for( int q = p + 1; q < ruler_id.length; q ++ ) {
										if( !empty[q] && ruler_id[p] == ruler_id[q] ) {
											same = true;
										}
									}
									if( !same ) {
										count ++;
									}
								}
							}
							int countFactions = 0;
							int factionIndex = 0;
							int countIndex = 0;
							int faction_id_index[] = new int[faction_id.length];
							int faction_count_index[] = new int[faction_id.length];
							boolean is_faction[] = new boolean[faction_id.length];
							for( int p = 0; p < faction_id.length; p ++ ) {
								boolean same = empty[p];
								if( !same  ) {
									for( int q = p + 1; q < faction_id.length; q ++ ) {
										if( !empty[q] && ( faction_id[p] == faction_id[q] || ruler_id[p] == ruler_id[q] ) ) {
											same = true;
										}
									}
									
									if( !same ) {
										countFactions ++;
									}
									
									boolean match = false;
									int match_index = -1;
									int match_count = -1;
									if( p > 0 ) {
										for( int q = p - 1; q >= 0; q -- ) {
											if( ( faction_id[p] == faction_id[q] || ruler_id[p] == ruler_id[q] ) && !empty[q] ) {
												match = true;
												match_index = faction_id_index[q];
												match_count = faction_count_index[q];
											}
										}
									}
									
									is_faction[p] = ( faction_id[p] != -1 );
									if( !match ) {
										faction_id_index[p] = factionIndex;
										faction_count_index[p] = countIndex;
										countIndex ++;
										factionIndex = p + 1 - 1 + 1;
									}
									else {
										faction_id_index[p] = match_index;
										faction_count_index[p] = match_count;
										factionIndex ++;
									}
								}
								/*else if( p == 0 ) {
									factionIndex ++;
								}*/
							}
							
							if( count > 1 ) {
								AgesOfStrifeServer.log.debug( "Armies in combat: " + ruler_id.length + ", different rulers: " + count + ", different factions: " + countFactions );

								long rulerLost[] = new long[count];
								long rulerKilled[] = new long[count];
								int send_ruler_id[] = new int[count];
								String rulerNames[] = new String[count];
								
								count = 0;
								int index = -1;
								for( int p = 0; p < ruler_id.length; p ++ ) {
									boolean same = empty[p];
									if( !same ) {
										for( int q = 0; q < p; q ++ ) {
											if( ruler_id[p] == ruler_id[q] ) {
												same = true;
												for( int o = 0; o < count; o ++ ) {
													if( ruler_id[p] == send_ruler_id[o] ) {
														index = o;
													}
												}
											}
										}
									}
									if( !same ) {
										rulerLost[count] = ( long ) ( lostScout[p] * 32l + lostInfantry[p] * 48 + lostCavalry[p] * 256 + lostArtillery[p] * 400 );
										rulerKilled[count] = ( long ) ( killedScout[p] * 32l + killedInfantry[p] * 48 + killedCavalry[p] * 256 + killedArtillery[p] * 400 );
										send_ruler_id[count] = ruler_id[p];
										rulerNames[count] = rulerName[p];
										count ++;
									}
									else if( !empty[p] ) {
										rulerLost[index] += ( long ) ( lostScout[p] * 32l + lostInfantry[p] * 48 + lostCavalry[p] * 256 + lostArtillery[p] * 400 );
										rulerKilled[index] += ( long ) ( killedScout[p] * 32l + killedInfantry[p] * 48 + killedCavalry[p] * 256 + killedArtillery[p] * 400 );
									}
								}
								
								newsItem.addText( "\n", false );
								newsItem.addText( "<table class=\"news-table\">", false );
								newsItem.addText( "<tr><th>", false );
								newsItem.addText( "Ruler", true );
								newsItem.addText( "</th><th align=\"right\">", false );
								newsItem.addText( "Lost in score", true );
								newsItem.addText( "</th><th align=\"right\">", false );
								newsItem.addText( "Killed in score", true );
								newsItem.addText( "</th><th align=\"right\">", false );
								newsItem.addText( "Ratio", true );
								newsItem.addText( "</th></tr>", false );
								
								for( int p = 0; p < send_ruler_id.length; p ++ ) {
									if( p % 2 == 0 ) {
										newsItem.addText( "<tr><td>", false );
									}
									else {
										newsItem.addText( "<tr class=\"even\"><td>", false );
									}
									newsItem.addText( rulerNames[p], false );
									newsItem.addText( "</td><td align=\"right\">" + Utils.formatNumber( "" + rulerLost[p] ) + "</td><td align=\"right\">" + Utils.formatNumber( "" + rulerKilled[p] ) + "</td><td align=\"right\">", false );
									if( rulerKilled[p] != 0 && rulerLost[p] != 0 ) {
										newsItem.addText( ( ( ( int ) Math.round( ( ( double ) rulerKilled[p] / ( double ) rulerLost[p] ) * 100 ) ) * 0.01 ) + "</td></tr>", false );
									}
									else {
										newsItem.addText( "-</td></tr>", false );
									}
								}
								newsItem.addText( "</table>", false );
								
								//boolean[] done = new boolean[armies.length];
								for( int p = 0; p < xp_gained.length; p ++ ) {
									/*if( !done[p] ) {
										for( int q = 0; q < armies.length; q ++ ) {
											if( ruler_id[p] == ruler_id[q] && !done[q] && !done[p] ) {
												stmtUpdate.execute( "INSERT INTO news ( ruler_id, type, subject, news, date, turn ) VALUES ( " + ruler_id[p] + ", 1, \"" + subject + "\", \"" + report + "\", \"" + date + "\", " + turn + " )" );
												done[p] = true;
											}
										}
									}*/
									if( ruler_id[p] != -1 ) {
										stmtUpdate.execute( "UPDATE ruler " +
												"SET experience = experience + " + xp_gained[p] + ", " +
												"scouts_killed = scouts_killed + " + killedScout[p] + ", " +
												"infantry_killed = infantry_killed + " + killedInfantry[p] + ", " +
												"cavalry_killed = cavalry_killed + " + killedCavalry[p] + ", " +
												"artillery_killed = artillery_killed + " + killedArtillery[p] + ", " +
												"scouts_lost = scouts_lost + " + lostScout[p] + ", " +
												"infantry_lost = infantry_lost + " + lostInfantry[p] + ", " +
												"cavalry_lost = cavalry_lost + " + lostCavalry[p] + ", " +
												"artillery_lost = artillery_lost + " + lostArtillery[p] + " " +
												"WHERE ruler_id = " + ruler_id[p] );
									}
								}
	
								newsItem.addTitleText( "Report from battle at", true );
								newsItem.addTitleText( " " + village, false );
								for( int p = 0; p < send_ruler_id.length; p ++ ) {
									if( send_ruler_id[p] != -1 ) {
										newsItem.insert( send_ruler_id[p], 1, turn, date );
									}
								}
							}
							
							// Check if we need to create a history item of this battle
							int turnModifier = 100000 + turn * 666;
							turnModifier = turnModifier > 2500000 ? 2500000 : turnModifier;  
							int winner = -1;
							long winningScore = -1;
							long differenceNeeded =  ( long ) ( totalXP * 0.0200 );
							if( totalXP >= 					1500000 + turnModifier ) {
								String title = "A large battle was seen at " + village;
								String txt = "";
								if( totalXP >= 			   20000000 + turnModifier ) {
									title = "An epic battle was seen at " + village;
									txt = "A battle of this scale is rarely seen and will surely end up in the history books!\nLet\\\'s hope the deaths of all these men is not in vain.\n";
								}
								else if( totalXP >= 		10000000 + turnModifier ) {
									title = "A gigantic battle was seen at " + village;
									txt = "So many forces have gathered to fight for their leaders, so many will die here.\nFrom where I\\\'m standing it is hard to grasp the number of men involved, my vision is mostly blocked by smoke.\n";
								}
								else if( totalXP >= 		5000000 + turnModifier ) {
									title = "A huge battle was seen at " + village;
								}
								else if( totalXP >= 		3000000 + turnModifier ) {
									title = "A very large battle was seen at " + village;
								}
								String[] factionText = new String[countFactions];
								long score[] = new long[countFactions];
								//int index = 0;
								for( int p = 0; p < faction_id.length; p ++ ) {
									//boolean same = ;
									if( !empty[p]  ) {
										/*for( int q = p + 1; q < faction_id.length; q ++ ) {
											if( !empty[q] && ( faction_id[p] == faction_id[q] || ruler_id[p] == ruler_id[q] ) ) {
												same = true;
											}
										}*/
										
										if( null == factionText[faction_count_index[p]] ) {
											factionText[faction_count_index[p]] = "";
										}
										
										String tmp = "";
										if( faction_id[p] != -1 ) {
											tmp = " from " + factionName[p];
										}
										
										factionText[faction_count_index[p]] += "" + name[p] + " lead by " + officerName[p] + " under command of " + rulerName[p] + tmp + "\n";
										score[faction_count_index[p]] += xp_gained[p];
									}
									//if( !same ) {
										//index ++;
									//}
								}
								
								if( countFactions > 2 ) {
									txt += "The armies involved in the battle at <a href=\\\"../operations/map.php?x=" + ( x - 20 ) + "&y=" + ( y - 20 ) + "\\\">" + village + "</a> are:\n\n";
								}
								else {
									txt += "The armies from the two battling sides at <a href=\\\"../operations/map.php?x=" + ( x - 20 ) + "&y=" + ( y - 20 ) + "\\\">" + village + "</a> are:\n\n";
								}
								
								for( int p = 0; p < factionText.length; p ++ ) {
									if( p > 0 ) {
										txt += "   against\n";
									}
									txt += factionText[p];
								}
								
								txt += "\n";
								
								for( int p = 0; p < score.length; p ++ ) {
									if( score[p] > winningScore ) {
										winner = p;
										winningScore = score[p];
									}
								}
								
								boolean easyWin = true;
								for( int p = 0; p < score.length; p ++ ) {
									if( winningScore < score[p] + differenceNeeded && winner != p ) {
										winner = -1;
										winningScore = -1;
										break;
									}
									else if( winningScore > differenceNeeded * 8 + score[p] ) {
										easyWin = false;										
									}
								}
								
								if( winner != -1 ) {
									for( int p = 0; p < faction_count_index.length; p ++ ) {
										if( faction_count_index[p] == winner ) {
											winner = faction_id_index[p];
											break;
										}
									}
									if( !easyWin ) {
										if( is_faction[faction_id_index[winner]] ) {
											txt += "It seems " + factionName[faction_id_index[winner]] + " is winning this battle.\n";
										}
										else {
											txt += "It seems " + rulerName[faction_id_index[winner]] + " is winning this battle.\n";
										}
									}
									else {
										if( is_faction[faction_id_index[winner]] ) {
											txt += factionName[faction_id_index[winner]] + "\\\'s forces seem much stronger in this battle.\n";
										}
										else {
											txt += "It seems " + rulerName[faction_id_index[winner]] + "s forces are much stronger in this battle.\n";
										}
									}
								}
								else {
									txt += "There doesn\\\'t seem to be a definite winner in this battle.\n";
								}
								
								txt += Utils.formatNumber( "" + killedTotal ) + " soldiers are reported dead or missing at the end of the day.";
								
								stmtUpdate.execute( "INSERT INTO history " +
										"( title, text, ruler_id, turn, date, visible ) " +
										"VALUES ( '" + title + "', '" + txt + "', -1, " + turn + ", '" + date + "', 1 )" );
								rs3 = stmt3.executeQuery( "SELECT history_id " +
										"FROM history " +
										"WHERE title = '" + title + "' AND text = '" + txt + "' AND ruler_id = -1 AND turn = " + turn + " AND date = '" + date + "' " +
										"LIMIT 1" );
								int history_id = -1;
								if( rs3.next() ) {
									history_id = rs3.getInt( "history_id" );
								}
								Utils.notifyOfHistory( rs3, stmt3, history_id );								
							}
							
							// This battle is significant, 
							// so let's set each involved battle date to today and give the winners a boast in morale
							if( totalXP > turnModifier ) {
								for( int p = 0; p < ruler_id.length; p ++ ) {
									if( !empty[p] ) {
										stmtUpdate.execute( "UPDATE ruler " +
												"SET last_battle = " + turn +
												" WHERE ruler_id = " + ruler_id[p] );
									}
								}
								
								if( winner != -1 ) {
									if( faction_id[faction_id_index[winner]] == -1 ) {
										stmtUpdate.execute( "UPDATE ruler " +
												"SET morale = morale + 0.1 " +
												"WHERE ruler_id = " + ruler_id[faction_id_index[winner]] );
									}
									else {
										String query = "UPDATE ruler " +
												"SET morale = morale + 0.1 " +
												"WHERE";
										String where = "";
										int check_ruler[] = new int[ruler_id.length];
										for( int p = 0; p < faction_id.length; p ++ ){
											check_ruler[p] = -1;
											if( !empty[p] && faction_id[faction_id_index[winner]] == faction_id[p] ) {
												boolean not_added = true;
												for( int q = p - 1; q > 0; q -- ) {
													if( check_ruler[q] == ruler_id[p] ) {
														not_added = false;
														break;
													}
												}
												if( not_added ) {
													if( where != "" ) {
														where += " OR";
													}
													where += " ruler_id = " + ruler_id[p];
													check_ruler[p] = ruler_id[p];
												}
											}
										}
										stmtUpdate.execute( query + where );
									}
								}
							}
						}
					}
				}
			}
		} catch ( Exception e ) {
			AgesOfStrifeServer.log.error( getStackError( e ) );
			e.printStackTrace();
		}
	}
	
	// let population grow in free villages?
	private void updateFactions() throws SQLException, NoSuchAlgorithmException{
		rs = stmt.executeQuery( "SELECT * FROM faction" );
		while ( rs.next() ) {
			int faction_id = rs.getInt( "faction_id" );
			AgesOfStrifeServer.log.debug( "updating faction: " + faction_id );
			int gold = rs.getInt( "gold" );
			int leader = rs.getInt( "leader" );
			String name = rs.getString( "name" );
			int food_support = rs.getInt( "farm_support" );
			int coal_support = rs.getInt( "coal_support" );
			int iron_support = rs.getInt( "iron_support" );
			int housingSupport = rs.getInt( "housing_support" );
			int draft = rs.getInt( "draft" );
			int alert = rs.getInt( "alert" );
			int nationalism = rs.getInt( "nationalism" );
			long score = 0;
			
			boolean debt = false;
				
			if( gold < 0 ) {
				debt = true;
			}
			rs2 = stmt2.executeQuery( "SELECT upkeep " +
					"FROM faction_types " +
					"WHERE faction_type_id = " + rs.getInt( "faction_type_id" ) );
			rs2.next();
			int upkeep = rs2.getInt( "upkeep" );
			int income = 0;
			rs2 = stmt2.executeQuery( "SELECT countdown, tax_set, ruler.ruler_id, member_time, score FROM faction_member JOIN ruler ON ruler.ruler_id = faction_member.ruler_id WHERE faction_id = " + faction_id + " AND invited = 0 AND requested = 0" );
			while ( rs2.next() ) {
				int countdown = rs2.getInt( "countdown" );
				int ruler_id = rs2.getInt( "ruler_id" );
				int tax_set = rs2.getInt( "tax_set" );
				score += rs2.getLong( "score" );
				stmtUpdate.executeUpdate( "UPDATE faction_member SET member_time = " + ( rs2.getInt( "member_time" ) + 1 ) + " WHERE ruler_id = " + ruler_id + " AND faction_id = " + faction_id );
				if( countdown > 0 ) {
					countdown --;
					if( countdown == 0 ) {
						if( ruler_id == leader ) {
							stmtUpdate.executeUpdate( "DELETE FROM faction WHERE faction_id = " + faction_id );
							stmtUpdate.executeUpdate( "DELETE FROM faction_member WHERE faction_id = " + faction_id );
						}
						stmtUpdate.executeUpdate( "DELETE FROM faction_member WHERE ruler_id = " + ruler_id + " AND faction_id = " + faction_id );
					}
					else {
						stmtUpdate.executeUpdate( "UPDATE faction_member SET countdown = " + countdown + " WHERE ruler_id = " + ruler_id + " AND faction_id = " + faction_id );
					}
				}
				else {
					rs3 = stmt3.executeQuery( "SELECT lastday_taxes, gold FROM ruler WHERE ruler_id = " + ruler_id );
					rs3.next();
					int pay = rs3.getInt( "lastday_taxes" ) * tax_set / 100;
					stmtUpdate.executeUpdate( "UPDATE faction_member SET gold_paid = " + pay + " WHERE ruler_id = " + ruler_id + " AND faction_id = " + faction_id );
					stmtUpdate.executeUpdate( "UPDATE ruler SET gold = " + ( rs3.getInt( "gold" ) - pay ) + " WHERE ruler_id = " + ruler_id );
					income += pay;
				}
			}
			
			gold += income;
			gold -= upkeep;
			rs3 = stmt3.executeQuery( "SELECT count(*) FROM village JOIN faction_member ON village.ruler_id = faction_member.ruler_id WHERE faction_id = " + faction_id + " AND requested = 0 AND invited = 0" );
			rs3.next();
			int villages = rs3.getInt( "count(*)" );
			int policy_cost = 0;
			if( food_support == 1 ) {
				policy_cost += villages * 4;
			}
			if( coal_support == 1 ) {
				policy_cost += villages * 3;
			}
			if( iron_support == 1 ) {
				policy_cost += villages * 3;
			}
			if( housingSupport == 1 ) {
				policy_cost += villages * 2;
			}
			if( draft == 1 ) {
				policy_cost += villages * 3;
			}
			if( alert == 1 ) {
				policy_cost += villages * 6;
			}
			if( nationalism == 1 ) {
				policy_cost += villages * 4;
			}
			gold -= policy_cost;
			
			if( gold < 0 ) {
				stmtUpdate.execute( "UPDATE faction " +
						"SET farm_support = 0, coal_support = 0, iron_support = 0, housing_support = 0, draft = 0, alert = 0, nationalism = 0 " +
						"WHERE faction_id = " + faction_id );
				if( debt ) {
					rs3 = stmt3.executeQuery( "SELECT countdown FROM faction_member WHERE ruler_id = " + leader + " AND faction_id = " + faction_id );
					if( rs3.next() && rs3.getInt( "countdown" ) == 0 ) {
						newsItem.clear();
						newsItem.addTitleText( name + " ", false );
						newsItem.addTitleText( "has been disbanded", false );
						newsItem.addText( name + " ", false );
						newsItem.addText( "has had its <strong class=\"gold\">gold</strong> reserve below zero for more then a day.", true );
						newsItem.addText( "\n", false );
						newsItem.addText( "The faction has been disbanded.", true );
						newsItem.insert( leader, 2, turn, date );
						rs2 = stmt2.executeQuery( "SELECT ruler_id FROM faction_member WHERE faction_id = " + faction_id + " AND invited = 0 AND requested = 0" );
						while ( rs2.next() ) {
							int ruler_id = rs2.getInt( "ruler_id" );
							stmtUpdate.executeUpdate( "UPDATE faction_member " +
									"SET countdown = 12 " +
									"WHERE ruler_id = " + ruler_id + " AND faction_id = " + faction_id );
							if( ruler_id != leader ) {
								newsItem.insert( ruler_id, 2, turn, date );
							}
						}
					}
				}
				else {
					newsItem.clear();
					newsItem.addTitleText( name + " ", false );
					newsItem.addTitleText( "is in debt", true );
					newsItem.addText( "The <strong class=\"gold\">gold</strong> reserve of", true );
					newsItem.addText( " " + name + " ", false );
					newsItem.addText( " is below zero.", true );
					newsItem.addText( "\n", false );
					newsItem.addText( "If the reserve doesn't rise above zero <strong class=\"gold\">gold</strong> tomorrow the faction will be disbanded!", true );
					newsItem.addText( "\n", false );
					newsItem.addText( "All faction policies are disabled, so we might get enough <strong class=\"gold\">gold</strong> tomorrow to keep the faction.", true );
					newsItem.insert( leader, 2, turn, date );
				}
			}
			stmtUpdate.executeUpdate( "UPDATE faction SET gold = " + gold + ", yesterday_gold_income = " + income + ", " +
					"score = " + score + ", policy_cost = " + policy_cost + " WHERE faction_id = " + faction_id );
		}
	}
	
	private void updateDemocraticFactions() throws SQLException {
		rs = stmt.executeQuery( "SELECT faction_id, leader " +
				"FROM faction " +
				"WHERE control_type = 1" );
		while( rs.next() ) {
			int faction_id = rs.getInt( "faction_id" );
			int leader = rs.getInt( "leader" );
			rs2 = stmt2.executeQuery( "SELECT count(*) " +
					"FROM faction_member " +
					"WHERE faction_id = " + faction_id + " AND invited = 0 AND requested = 0" );
			rs2.next();
			int totalMembers = rs2.getInt( 1 );
			int[] countVotes = new int[totalMembers];
			int[] ruler_id = new int[totalMembers];
			rs2 = stmt2.executeQuery( "SELECT ruler_id " +
					"FROM faction_member " +
					"WHERE faction_id = " + faction_id + " AND invited = 0 AND requested = 0 " );
			int index = 0;
			while( rs2.next() ) {
				ruler_id[index] = rs2.getInt( "ruler_id" );
				index ++;
			}
			rs2 = stmt2.executeQuery( "SELECT leader_vote " +
					"FROM faction_member " +
					"WHERE faction_id = " + faction_id + " AND invited = 0 AND requested = 0 " );
			while( rs2.next() ) {
				int votedFor = rs2.getInt( "leader_vote" );
				if( votedFor != -1 ) {
					for( int i = 0; i < ruler_id.length; i ++ ) { 
						if( ruler_id[i] == votedFor ) {
							countVotes[i] ++;
							break;
						}
					}
				}
			}
			
			int mostVotes = 0;
			for( int i = 0; i < countVotes.length; i ++ ) {
				if( countVotes[i] > mostVotes ) {
					mostVotes = countVotes[i];
				}
			}
			
			boolean[] winners = new boolean[totalMembers];
			int totalWinners = 0;
			for( int i = 0; i < countVotes.length; i ++ ) {
				if( countVotes[i] == mostVotes ) {
					winners[i] = true;
					totalWinners ++;
				}
			}
			
			boolean leaderRemains = false;
			for( int i = 0; i < countVotes.length; i ++ ) {
				if( winners[i] && ruler_id[i] == leader ) {
					leaderRemains = true;
					break;
				}
			}
			
			if( !leaderRemains ) {
				int randomSelect = ( int ) ( Math.random() * totalWinners );
				int winnerIndex = -1;
				int count = 0;
				for( int i = 0; i < countVotes.length; i ++ ) {
					if( winners[i] && count == randomSelect ) {
						winnerIndex = i;
						break;
					}
					else if( winners[i] ) {
						count ++;
					}
				}
				
				rs2 = stmt2.executeQuery( "SELECT access " +
						"FROM faction_member " +
						"WHERE ruler_id = " + ruler_id[winnerIndex] );
				rs2.next();
				int swapAccess = rs2.getInt( "access" );
				
				stmtUpdate.execute( "UPDATE faction_member " +
						"SET access = " + swapAccess + " " +
						"WHERE ruler_id = " + leader + " AND faction_id = " + faction_id );
				
				stmtUpdate.execute( "UPDATE faction_member " +
						"SET access = 10 " +
						"WHERE ruler_id = " + ruler_id[winnerIndex] + " AND faction_id = " + faction_id );
				
				stmtUpdate.execute( "UPDATE faction " +
						"SET leader = " + ruler_id[winnerIndex] + " " +
						"WHERE faction_id = " + faction_id );
			}
		}
	}
	
	private void updateTrade() throws SQLException, NoSuchAlgorithmException {
		// get current resource values
		rs = stmt.executeQuery( "SELECT coal_gold, iron_gold, food_gold " +
				"FROM game" );
		rs.next();
		
		double coal_gold = rs.getDouble( "coal_gold" );
		double iron_gold = rs.getDouble( "iron_gold" );
		double food_gold = rs.getDouble( "food_gold" );
		
		// Deal with completed trades
		rs = stmt.executeQuery( "SELECT * " +
				"FROM trade " +
				"WHERE accepted = 1 AND completed = 0" );
		while ( rs.next() ) {
			int trade_id = rs.getInt( "trade_id" );
			int ruler_id = rs.getInt( "ruler_id" );
			int from_faction = rs.getInt( "from_faction" );
			int accept_faction = rs.getInt( "accept_faction" );
			int accept_ruler = rs.getInt( "accept_ruler" );
			int gold_offer = rs.getInt( "gold_offer" );
			int iron_offer = rs.getInt( "iron_offer" );
			int coal_offer = rs.getInt( "coal_offer" );
			int food_offer = rs.getInt( "food_offer" );
			int gold_want = rs.getInt( "gold_want" );
			int iron_want = rs.getInt( "iron_want" );
			int coal_want = rs.getInt( "coal_want" );
			int food_want = rs.getInt( "food_want" );
			String from_name = "";
			String to_name = "";
			int news1_id = -1;
			int news2_id = -1;
			boolean fromTranslate = false;
			
			if( ruler_id != -1 ) { // a trade offered by a ruler
				rs3 = stmt3.executeQuery( "SELECT gold, coal, iron, name " +
						"FROM ruler " +
						"WHERE ruler_id = " + ruler_id );
				if( rs3.next() ) {
					from_name = rs3.getString( "name" );
					news1_id = ruler_id;
					stmtUpdate.execute( "UPDATE ruler " +
							"SET gold = " + ( rs3.getInt( "gold" ) + gold_want ) + ", " +
									"iron = " + ( rs3.getInt( "iron" ) + iron_want ) + ", " +
									"coal = " + ( rs3.getInt( "coal" ) + coal_want ) + ", " +
									"food = food + " + food_want + " " +
							"WHERE ruler_id = " + ruler_id );
				}
			}
			else if( from_faction != -1 ) { // a trade offered by a faction
				rs2 = stmt2.executeQuery( "SELECT gold, coal, iron, name, leader " +
						"FROM faction " +
						"WHERE faction_id = " + from_faction );
				if( rs2.next() ) {
					from_name = rs2.getString( "name" );
					news1_id = rs2.getInt( "leader" );
					stmtUpdate.execute( "UPDATE faction " +
							"SET gold = " + ( rs2.getInt( "gold" ) + gold_want ) + ", " +
									"iron = " + ( rs2.getInt( "iron" ) + iron_want ) + ", " +
									"coal = " + ( rs2.getInt( "coal" ) + coal_want ) + ", " +
									"food = food + " + food_want + " " +
								" WHERE faction_id = " + from_faction );
				}
			}
			else {
				from_name = "Independent trader";
				fromTranslate = true;
			}
			
			if( accept_faction != -1 ) { // faction accepted
				rs2 = stmt2.executeQuery( "SELECT gold, coal, iron, food, name, leader FROM faction WHERE faction_id = " + accept_faction );
				if( rs2.next() ) {
					to_name = rs2.getString( "name" );
					news2_id = rs2.getInt( "leader" );
					stmtUpdate.execute( "UPDATE faction " +
							"SET gold = " + ( rs2.getInt( "gold" ) + gold_offer ) + ", " +
									"iron = " + ( rs2.getInt( "iron" ) + iron_offer ) + ", " +
									"coal = " + ( rs2.getInt( "coal" ) + coal_offer ) + ", " +
									"food = " + ( rs2.getInt( "food" ) + food_offer ) + " " +
							"WHERE faction_id = " + accept_faction );
				}
			}
			else if( accept_ruler != -1 ) { // ruler accepted
				rs3 = stmt3.executeQuery( "SELECT gold, coal, iron, name FROM ruler WHERE ruler_id = " + accept_ruler );
				if( rs3.next() ) {
					to_name = rs3.getString( "name" );
					news2_id = accept_ruler;
					stmtUpdate.execute( "UPDATE ruler " +
							"SET gold = " + ( rs3.getInt( "gold" ) + gold_offer ) + ", " +
									"iron = " + ( rs3.getInt( "iron" ) + iron_offer ) + ", " +
									"coal = " + ( rs3.getInt( "coal" ) + coal_offer ) + ", " +
									"food = food + " + food_offer + " " +
							"WHERE ruler_id = " + accept_ruler );
				}
			}
			
			newsItem.clear();
			newsItem.addTitleText( "Trade completed", true );
			newsItem.addText( "Trade offered by", true );
			newsItem.addText( ": ", false );
			newsItem.addText( from_name, fromTranslate );
			newsItem.addText( "\n", false );
			newsItem.addText( "Trade accepted by", true );
			newsItem.addText( ": " + to_name + "\n", false );
			newsItem.addText( "Traded", true );
			newsItem.addText( ":\n", false );
			if( gold_offer > 0 ) {
				newsItem.addText( "<strong class=\"gold\">" + Utils.formatNumber( "" + gold_offer ) + "</strong>\n", false );
			}
			if( iron_offer > 0 ) {
				newsItem.addText( "<strong class=\"iron\">" + Utils.formatNumber( "" + iron_offer ) + "</strong>\n", false );
			}
			if( coal_offer > 0 ) {
				newsItem.addText( "<strong class=\"coal\">" + Utils.formatNumber( "" + coal_offer ) + "</strong>\n", false );
			}
			if( food_offer > 0 ) {
				newsItem.addText( "<strong class=\"food\">" + Utils.formatNumber( "" + food_offer ) + "</strong>\n", false );
			}

			newsItem.addText( "for", true );
			newsItem.addText( "\n", false );
			
			if( gold_want > 0 ) {
				newsItem.addText( "<strong class=\"gold\">" + Utils.formatNumber( "" + gold_want ) + "</strong>\n", false );
			}
			if( iron_want > 0 ) {
				newsItem.addText( "<strong class=\"iron\">" + Utils.formatNumber( "" + iron_want ) + "</strong>\n", false );
			}
			if( coal_want > 0 ) {
				newsItem.addText( "<strong class=\"coal\">" + Utils.formatNumber( "" + coal_want ) + "</strong>\n", false );
			}
			if( food_want > 0 ) {
				newsItem.addText( "<strong class=\"food\">" + Utils.formatNumber( "" + food_want ) + "</strong>\n", false );
			}
			
			if( news1_id != -1 ) {
				newsItem.insert( news1_id, 2, turn, date );
			}
			
			if( news2_id != -1 ) {
				newsItem.insert( news2_id, 2, turn, date );
			}
			
			stmtUpdate.execute( "UPDATE trade " +
					"SET completed = 1, complete_turn = " + turn + " " +
					"WHERE trade_id = " + trade_id );
		}
			
		rs = stmt.executeQuery( "SELECT count(*) " +
				"FROM trade " +
				"WHERE turn + time < " + turn + " AND expired = 0 AND completed = 0 AND accepted = 0" );
		if( rs.next() ) {
			AgesOfStrifeServer.log.debug( "Number of expired trades: " + rs.getInt( "count(*)" ) );
		}
		
		// Deal with expired trades
		rs = stmt.executeQuery( "SELECT * " +
				"FROM trade " +
				"WHERE ( turn + time ) < " + turn + " AND expired = 0 AND completed = 0 AND accepted = 0" );
		while ( rs.next() ) {
			int trade_id = rs.getInt( "trade_id" );
			int ruler_id = rs.getInt( "ruler_id" );
			int from_faction = rs.getInt( "from_faction" );
			int gold_offer = rs.getInt( "gold_offer" );
			int iron_offer = rs.getInt( "iron_offer" );
			int coal_offer = rs.getInt( "coal_offer" );
			int food_offer = rs.getInt( "food_offer" );
			int gold_want = rs.getInt( "gold_want" );
			int iron_want = rs.getInt( "iron_want" );
			int coal_want = rs.getInt( "coal_want" );
			int food_want = rs.getInt( "food_want" );
			String from_name = "";
			int news1_id = -1;

			if( ruler_id != -1 ) { // a trade offered by a ruler
				rs3 = stmt3.executeQuery( "SELECT gold, coal, iron, name FROM ruler WHERE ruler_id = " + ruler_id );
				if( rs3.next() ) {
					from_name = rs3.getString( "name" );
					news1_id = ruler_id;
					AgesOfStrifeServer.log.debug( "Expired trade for: " + from_name + " with ruler_id: " + news1_id );
					stmtUpdate.execute( "UPDATE ruler " +
							"SET gold = " + ( rs3.getInt( "gold" ) + gold_offer ) + ", " +
									"iron = " + ( rs3.getInt( "iron" ) + iron_offer ) + ", " +
									"coal = " + ( rs3.getInt( "coal" ) + coal_offer ) + ", " +
									"food = food + " + food_offer + " " +
							"WHERE ruler_id = " + ruler_id );
				}
			}
			else if( from_faction != -1 ) { // a trade offered by a faction
				rs2 = stmt2.executeQuery( "SELECT gold, coal, iron, name, leader FROM faction WHERE faction_id = " + from_faction );
				if( rs2.next() ) {
					from_name = rs2.getString( "name" );
					news1_id = rs2.getInt( "leader" );
					stmtUpdate.execute( "UPDATE faction " +
							"SET gold = " + ( rs2.getInt( "gold" ) + gold_offer ) + ", " +
									"iron = " + ( rs2.getInt( "iron" ) + iron_offer ) + ", " +
									"coal = " + ( rs2.getInt( "coal" ) + coal_offer ) + ", " +
									"food = food + " + food_offer + " " +
							"WHERE faction_id = " + from_faction );
				}
			}

			if( news1_id != -1 ) { 
				newsItem.clear();
				newsItem.addTitleText( "Trade expired", true );
				newsItem.addText( "Our trade offer expired.", true );
				newsItem.addText( "\n", false );
				newsItem.addText( "The resources we offered have been returned.", true );
				newsItem.addText( "\n", false );
				newsItem.addText( "We wanted to trade", true );
				newsItem.addText( ":\n", false );
				newsItem.addText( "<strong class=\"gold\">" + Utils.formatNumber( "" + gold_offer ) + "</strong> ", false );
				newsItem.addText( "gold", true );
				newsItem.addText( ", <strong class=\"iron\">" + Utils.formatNumber( "" + iron_offer ) + "</strong> ", false );
				newsItem.addText( "iron", true );
				newsItem.addText( ", <strong class=\"coal\">" + Utils.formatNumber( "" + coal_offer ) + "</strong> ", false );
				newsItem.addText( "coal", true );
				newsItem.addText( " ", false );
				newsItem.addText( "and", true );
				newsItem.addText( " <strong class=\"food\">" + Utils.formatNumber( "" + food_offer ) + "</strong> ", false );
				newsItem.addText( "food", true );
				newsItem.addText( "\n", false );
				newsItem.addText( "for", true );
				newsItem.addText( "<strong class=\"gold\">" + Utils.formatNumber( "" + gold_want ) + "</strong> ", false );
				newsItem.addText( "gold", true );
				newsItem.addText( ", <strong class=\"iron\">" + Utils.formatNumber( "" + iron_want ) + "</strong> ", false );
				newsItem.addText( "iron", true );
				newsItem.addText( ", <strong class=\"coal\">" + Utils.formatNumber( "" + coal_want ) + "</strong> ", false );
				newsItem.addText( "coal", true );
				newsItem.addText( " ", false );
				newsItem.addText( "and", true );
				newsItem.addText( " <strong class=\"food\">" + Utils.formatNumber( "" + food_want ) + "</strong> ", false );
				newsItem.addText( "food", true );
				newsItem.addText( "\n", false );
				newsItem.insert( news1_id, 2, turn, date );
			}
			
			stmtUpdate.execute( "UPDATE trade SET expired = 1, complete_turn = " + turn + " WHERE trade_id = " + trade_id );
		}
		
		// Add public independent trades
		addIndependentTrades( -1, iron_gold, coal_gold, food_gold );
		
		// Add independent trades for users with premium turns
		rs = stmt.executeQuery( "SELECT ruler_id " +
				"FROM ruler " +
				"JOIN users ON ruler.user_id = users.user_id " +
				"WHERE premium > 10" );
		while( rs.next() ) {
			addIndependentTrades( rs.getInt( 1 ), iron_gold, coal_gold, food_gold );
		}
	}
	
	private void addIndependentTrades( int rulerId, double iron_gold, double coal_gold, double food_gold ) throws SQLException {
		AgesOfStrifeServer.log.debug( "addIndependentTrades( " + rulerId + " );" );
		int maxGoldValue = 3000 + turn * 3;
		boolean noGoldOffered = false;
		
		if( turn < 500 ) {
			noGoldOffered = true;
		}
		
		rs2 = stmt2.executeQuery( "SELECT count(*) " +
				"FROM trade " +
				"WHERE expired = 0 AND completed = 0 " +
					"AND accepted = 0 AND ruler_id = -1 " +
					"AND from_faction = -1 AND private_id = " + rulerId );
		if( rs2.next() ) {
			int toAdd = 36;
			if( rulerId != -1 ) {
				toAdd = 5;
			}
			toAdd -= rs2.getInt( 1 );
			double iron_coal = iron_gold / coal_gold;
			double iron_food = iron_gold / food_gold;
			double food_coal = food_gold / coal_gold;

			for( int i = 0; i < toAdd; i ++ ) {
				if( Math.random() > 0.9 ) {
					AgesOfStrifeServer.log.debug( "Adding independent trade offer." );
					int gold_offer = 0;
					int iron_offer = 0;
					int coal_offer = 0;
					int food_offer = 0;
					int gold_want = 0;
					int iron_want = 0;
					int coal_want = 0;
					int food_want = 0;
					
					int offer;
					if( noGoldOffered ) {
						offer = ( int ) ( Math.random() * 3 ) + 1;
					}
					else {
						offer = ( int ) ( Math.random() * 4 );
					}
					double chance = Math.random(); 
					if( offer == 0 ) {
						gold_offer = ( int ) Math.round( Math.random() * maxGoldValue + 0.5 );
						if( chance > 0.66 ) {
							iron_want = ( int ) ( gold_offer / iron_gold + 0.5 );
							iron_want += ( int ) ( 0.1 * Math.random() * iron_want - 0.05 * iron_want );
						}
						else if( chance > 0.33 ) {
							coal_want = ( int ) ( gold_offer / coal_gold + 0.5 );
							coal_want += ( int ) ( 0.1 * Math.random() * coal_want - 0.05 * coal_want );
						}
						else {
							food_want = ( int ) ( gold_offer / food_gold + 0.5 );
							food_want += ( int ) ( 0.1 * Math.random() * food_want - 0.05 * food_want );
						}
					}
					else if( offer == 1 ) {
						iron_offer = ( int ) Math.round( Math.random() * maxGoldValue / iron_gold + 0.5 );
						if( chance > 0.66 ) {
							gold_want = ( int ) ( iron_offer * iron_gold + 0.5 );
							gold_want += ( int ) ( 0.1 * Math.random() * gold_want - 0.05 * gold_want );
						}
						else if( chance > 0.33 ) {
							food_want = ( int ) ( iron_offer * iron_food + 0.5 );
							food_want += ( int ) ( 0.1 * Math.random() * food_want - 0.05 * food_want );
						}
						else {
							coal_want = ( int ) ( iron_offer * iron_coal + 0.5 );
							coal_want += ( int ) ( 0.1 * Math.random() * coal_want - 0.05 * coal_want );
						}
					}
					else if( offer == 2 ) {
						food_offer = ( int ) Math.round( Math.random() * maxGoldValue / food_gold + 0.5 );
						if( chance > 0.66 ) {
							gold_want = ( int ) ( food_offer * food_gold + 0.5 );
							gold_want += ( int ) ( 0.1 * Math.random() * gold_want - 0.05 * gold_want );
						}
						else if( chance > 0.33 ) {
							iron_want = ( int ) ( food_offer / iron_food + 0.5 );
							iron_want += ( int ) ( 0.1 * Math.random() * iron_want - 0.05 * iron_want );
						}
						else {
							coal_want = ( int ) ( food_offer * food_coal + 0.5 );
							coal_want += ( int ) ( 0.1 * Math.random() * coal_want - 0.05 * coal_want );
						}
					}
					else {
						coal_offer = ( int ) Math.round( Math.random() * maxGoldValue / coal_gold + 0.5 );
						if( chance > 0.66 ) {
							gold_want = ( int ) ( coal_offer * coal_gold + 0.5 );
							gold_want += ( int ) ( 0.1 * Math.random() * gold_want - 0.05 * gold_want );
						}
						else if( chance > 0.33 ) {
							food_want = ( int ) ( coal_offer / food_coal + 0.5 );
							food_want += ( int ) ( 0.1 * Math.random() * food_want - 0.05 * food_want );
						}
						else {
							iron_want = ( int ) ( coal_offer / iron_coal + 0.5 );
							iron_want += ( int ) ( 0.1 * Math.random() * iron_want - 0.05 * iron_want );
						}
					}
					stmtUpdate.execute( "INSERT INTO trade " +
							"( gold_offer, iron_offer, coal_offer, food_offer, gold_want, iron_want, coal_want, food_want, turn, time, date, private_id ) " +
							"VALUES ( " + gold_offer + ", " + iron_offer + ", " + coal_offer + ", " + food_offer + ", " + gold_want + ", " + iron_want + ", " + coal_want + ", "  + food_want + ", " + turn + ", 24, '" + date + "', " + rulerId + " )" );
				}
			}
		}		
	}
	
	/**
	 * @throws SQLException
	 * Add warrior points per ruler
	 */
	private void updateWarriorPoints() throws SQLException {
		rs = stmt.executeQuery( "SELECT count(*) FROM ruler" );
		if( rs.next() ) {
			int rulers = rs.getInt( 1 );
			if( rulers > 0 ) {
				rs = stmt.executeQuery( "SELECT experience, warrior_points, ruler_id FROM ruler" );
				while( rs.next() ) {
					long experience = rs.getLong( "experience" );
					long warriorPoints = rs.getLong( "warrior_points" );
					int ruler_id = rs.getInt( "ruler_id" );
					if( experience != 0 ) {
						rs2 = stmt2.executeQuery( "SELECT count(*) FROM ruler WHERE experience < " + experience + " AND experience > 0" );
						if( rs2.next() ) {
							stmtUpdate.execute( "UPDATE ruler SET warrior_points = " + ( warriorPoints + rs2.getInt( 1 ) + 1 ) + " WHERE ruler_id = " + ruler_id );
						}
					}
				}
			}
		}
		rs = stmt.executeQuery( "SELECT faction_id FROM faction" );
		while( rs.next() ) {
			rs2 = stmt2.executeQuery( "SELECT SUM( warrior_points ) FROM ruler " +
					"JOIN faction_member ON ruler.ruler_id = faction_member.ruler_id WHERE faction_id = " + rs.getInt( "faction_id" ) );
			if( rs2.next() ) {
				stmtUpdate.execute( "UPDATE faction SET war_points = " + rs2.getLong( 1 ) + " WHERE faction_id = " + rs.getInt( "faction_id" ) );
			}
		}
	}

	private void updateEconomyPoints() throws SQLException {
		rs = stmt.executeQuery( "SELECT count(*) FROM ruler" );
		if( rs.next() ) {
			int rulers = rs.getInt( 1 );
			if( rulers > 0 ) {
				rs = stmt.executeQuery( "SELECT score, economy_points, ruler_id FROM ruler" );
				while( rs.next() ) {
					long score = rs.getLong( "score" );
					long economyPoints = rs.getLong( "economy_points" );
					int ruler_id = rs.getInt( "ruler_id" );
					if( score != 0 ) {
						rs2 = stmt2.executeQuery( "SELECT count(*) FROM ruler WHERE score < " + score );
						if( rs2.next() ) {
							stmtUpdate.execute( "UPDATE ruler SET economy_points = " + ( economyPoints + rs2.getInt( 1 ) + 1 ) + " WHERE ruler_id = " + ruler_id );
						}
					}
				}
			}
		}
		rs = stmt.executeQuery( "SELECT faction_id FROM faction" );
		while( rs.next() ) {
			rs2 = stmt2.executeQuery( "SELECT SUM( economy_points ) FROM ruler " +
					"JOIN faction_member ON ruler.ruler_id = faction_member.ruler_id WHERE faction_id = " + rs.getInt( "faction_id" ) );
			if( rs2.next() ) {
				stmtUpdate.execute( "UPDATE faction SET economy_points = " + rs2.getLong( 1 ) + " WHERE faction_id = " + rs.getInt( "faction_id" ) );
			}
		}
	}
	
	private long updateArmies( int ruler_id, long score ) throws SQLException, NoSuchAlgorithmException {
		// update armies
		rs = stmt.executeQuery( "SELECT * FROM army WHERE ruler_id = " + ruler_id );
		while ( rs.next() ) {
			int scout = rs.getInt( "scout" );
			int infantry = rs.getInt( "infantry" );
			int cavalry = rs.getInt( "cavalry" );
			int artillery = rs.getInt( "artillery" );
			int size = scout + infantry + cavalry + artillery;
			int officer_id = rs.getInt( "officer_id" );
			int maxsize = 10;
			int fortified = rs.getInt( "fortified" );
			int army_travel = rs.getInt( "travel" );
			int army_id = rs.getInt( "army_id" );
			int old_max_fatigue = rs.getInt( "max_fatigue" );
			int max_fatigue;
			int fatigue = rs.getInt( "fatigue" );
			String armyName = rs.getString( "name" );
			int training = rs.getInt( "training" );
			int mission = rs.getInt( "mission" );
			int x = rs.getInt( "x" );
			int y = rs.getInt( "y" );
			
			boolean moving = false;
			
			if( scout + infantry + cavalry + artillery > 0 ) {
				if( artillery > 0 && cavalry < artillery ) {
					max_fatigue = 10;
				}
				else if( artillery > 0 && cavalry >= artillery ) {
					max_fatigue = 25;
				}
				else if( cavalry > 0 && scout == 0 && infantry == 0 && artillery == 0 ) {
					max_fatigue = 40;
				}
				else {
					max_fatigue = 25;
				}
				
				if( max_fatigue != old_max_fatigue ) {
					stmtUpdate.execute( "UPDATE army " +
							"SET max_fatigue = " + max_fatigue + " " +
							"WHERE army_id = " + army_id );
				}
			}
			else {
				max_fatigue = 0;
			}
			
			score += scout * 32l + infantry * 48l + cavalry * 256l + artillery * 400l;
			//System.out.println( "score army: " + ( scout * 20 + infantry * 104 + cavalry * 316 + artillery * 448 ) );
			
			// determine army maximum size
			rs2 = stmt2.executeQuery( "SELECT rank " +
					"FROM officers " +
					"WHERE officer_id = " + officer_id );
			if( rs2.next() ) {
				maxsize = 50;
				int rank = rs2.getInt( "rank" );
				for( int i = 0; i < rank; i ++ ) {
					maxsize *= 5;
				}
			}
			
			// handle army training 
			rs2 = stmt2.executeQuery( "SELECT * " +
					"FROM transfer " +
					"WHERE ( from_army_id = " + army_id + " OR to_army_id = " + army_id + " ) AND complete_turn <= " + turn );
			if( rs2.next() ) {
				//training --;
				int from_army_id = rs2.getInt( "from_army_id" );
				//int to_army_id = rs2.getInt( "to_army_id" );
				int scouts_transfer = rs2.getInt( "scouts" );
				int infantry_transfer = rs2.getInt( "infantry" );
				int cavalry_transfer = rs2.getInt( "cavalry" );
				int artillery_transfer = rs2.getInt( "artillery" );
				int transfer_id = rs2.getInt( "transfer_id" );
				int officer_id_transfer = rs2.getInt( "officer_id" );
				if( army_id == from_army_id ) { // move units from this army
					if( officer_id_transfer != -1 ) {
						stmtUpdate.execute( "UPDATE army " +
								"SET officer_id = -1 " +
								"WHERE army_id = " + army_id );
					}
					else {
						if( scouts_transfer > scout ) {
							scouts_transfer = scout;
						}
						if( infantry_transfer > infantry ) {
							infantry_transfer = infantry;
						}
						if( cavalry_transfer > cavalry ) {
							cavalry_transfer = cavalry;
						}
						if( artillery_transfer > artillery ) {
							artillery_transfer = artillery;
						}
						
						stmtUpdate.execute( "UPDATE ruler SET scouts = scouts + " + scouts_transfer + ", " +
								"infantry = infantry + " + infantry_transfer + ", " +
								"cavalry = cavalry + " + cavalry_transfer + ", " +
								"artillery = artillery + " + artillery_transfer + " " +
								"WHERE ruler_id = " + ruler_id );
						stmtUpdate.execute( "UPDATE army " +
								"SET scout = scout - " + scouts_transfer + ", " +
								"infantry = infantry - " + infantry_transfer + ", " +
								"cavalry = cavalry - " + cavalry_transfer + ", " +
								"artillery = artillery - " + artillery_transfer + " " +
								"WHERE army_id = " + army_id );
					}
				}
				else { // move units to this army
					if( officer_id_transfer != -1 ) {
						stmtUpdate.execute( "UPDATE army SET officer_id = " + officer_id_transfer + " WHERE army_id = " + army_id );
					}
					else {
						rs3 = stmt3.executeQuery( "SELECT scouts, infantry, cavalry, artillery " +
								"FROM ruler " +
								"WHERE ruler_id = " + ruler_id );
						rs3.next();
						int reserveScouts = rs3.getInt( "scouts" );
						int reserveInfantry = rs3.getInt( "infantry" );
						int reserveCavalry = rs3.getInt( "cavalry" );
						int reserveArtillery = rs3.getInt( "artillery" );
						if( scouts_transfer > reserveScouts ) {
							scouts_transfer = reserveScouts;
						}
						if( infantry_transfer > reserveInfantry ) {
							infantry_transfer = reserveInfantry;
						}
						if( cavalry_transfer > reserveCavalry ) {
							cavalry_transfer = reserveCavalry;
						}
						if( artillery_transfer > reserveArtillery ) {
							artillery_transfer = reserveArtillery;
						}
						
						stmtUpdate.execute( "UPDATE army SET scout = scout + " + scouts_transfer + ", " +
								"infantry = infantry + " + infantry_transfer + ", " +
								"cavalry = cavalry + " + cavalry_transfer + ", " +
								"artillery = artillery + " + artillery_transfer + " WHERE army_id = " + army_id );
						stmtUpdate.execute( "UPDATE ruler SET scouts = scouts - " + scouts_transfer + ", " +
								"infantry = infantry - " + infantry_transfer + ", " +
								"cavalry = cavalry - " + cavalry_transfer + ", " +
								"artillery = artillery - " + artillery_transfer + " " +
								"WHERE ruler_id = " + ruler_id );
					}
				}
				
				// remove the transfer item and set the army to not training anymore
				stmtUpdate.execute( "DELETE FROM transfer WHERE transfer_id = " + transfer_id );
				if( officer_id_transfer == -1 ) {
					stmtUpdate.executeUpdate( "UPDATE army SET training = 0 WHERE army_id = " + army_id );
				}
			}

			// count transfers for this army
			rs2 = stmt2.executeQuery( "SELECT count(*) " +
					"FROM transfer " +
					"WHERE ( from_army_id = " + army_id + " OR to_army_id = " + army_id + " )" );
			if( rs2.next() ) {
				int transfers = rs2.getInt( 1 );
				// if the army exceeds it's maximum size, some soldiers will desert (only when not already transferring)
				if( transfers == 0 && size > maxsize && training == 0 ) {
					AgesOfStrifeServer.log.debug( "Soldiers are fleeing from army: " + army_id );
					int scoutFlee = ( int ) ( scout * 0.3 );
					int infantryFlee = ( int ) ( infantry * 0.3 );
					int cavalryFlee = ( int ) ( cavalry * 0.3 );
					int artilleryFlee = ( int ) ( artillery * 0.3 );
					
					scout -= scoutFlee;
					infantry -= infantryFlee;
					cavalry -= cavalryFlee;
					artillery -= artilleryFlee;
					
					/*stmtUpdate.execute( "UPDATE army " +
							"SET scout = " + scout + ", " +
								"infantry = " + infantry + ", " +
								"cavalry = " + cavalry + ", " +
								"artillery = " + artillery + " " +
							"WHERE army_id = " + army_id );*/

					newsItem.clear();
					newsItem.addTitleText( "People have fled from", true );
					newsItem.addTitleText( " " + armyName, false );
					newsItem.addText( "Some soldiers have deserted our army.", true );
					newsItem.addText( "\n", false );
					newsItem.addText( "This is caused by the lack of a proper commanding officer, make sure the commanding officer is of high enough rank.", true );
					newsItem.addText( "\n\n", false );
					newsItem.addText( "Most of the fled soldiers will rejoin your global reserves in 12 days.", true );
					newsItem.addText( "\n", false );
									
					newsItem.insert( ruler_id, 1, turn, date );
					String query = "INSERT INTO transfer ( scouts, infantry, cavalry, artillery, from_army_id, complete_turn, ruler_id ) " +
						"VALUES ( " + ( int ) ( scoutFlee * 0.9 ) + ", " + ( int ) ( infantryFlee * 0.9 ) + ", " + ( int ) ( cavalryFlee * 0.9 ) + ", " + ( int ) ( artilleryFlee * 0.9 ) + ", " + army_id + ", " + ( turn + 12 ) + ", " + ruler_id + " )";
					stmtUpdate.execute( query );
				}
			}

			if( mission > 0 && training == 0 ) { // handle armies on a mission
				mission --;
				int mission_type = rs.getInt( "mission_type" );
				if( fortified == 0 && mission_type == 4 && mission == 5 ) { 
					// Has been fortifying for 3 turns, let's start bombarding
					stmtUpdate.executeUpdate( "UPDATE army SET bombard = 1 WHERE army_id = " + army_id );
				}
				else if( fortified == 1 && mission_type == 5 && mission == 2 ) { 
					// Has been digging out for 2 turns, let's stop bombarding
					stmtUpdate.executeUpdate( "UPDATE army SET bombard = 0 WHERE army_id = " + army_id );
				}
				
				if( mission == 0 ) {
					newsItem.clear();
					newsItem.addText( "Mission report", true );
					newsItem.addText( ":\n\n", false );
					if( mission_type == 4 || mission_type == 5 ) { // Fortify/Dig out mission complete
						if( fortified == 1 ) {
							stmtUpdate.executeUpdate( "UPDATE army SET bombard = 0, fortified = 0 WHERE army_id = " + army_id );
						}
						else {
							stmtUpdate.executeUpdate( "UPDATE army SET fortified = 1, bombard = 1 WHERE army_id = " + army_id );
						}
					}
					else { // Any scout mission
						int difference = 0;
						int maxResults = 0;
						if( mission_type == 0 ) {
							newsItem.addTitleText( "Small scout mission completed by", true );
							newsItem.addTitleText( " " + armyName, false );
							difference = 5;
							maxResults = 2;
						}
						else if( mission_type == 1 ) {
							newsItem.addTitleText( "Medium scout mission completed by", true );
							newsItem.addTitleText( " " + armyName, false );
							difference = 10;
							maxResults = 4;
						}
						else if( mission_type == 2 ) {
							newsItem.addTitleText( "Large scout mission completed by", true );
							newsItem.addTitleText( " " + armyName, false );
							difference = 15;
							maxResults = 7;
						}
						else if( mission_type == 3 ) {
							newsItem.addTitleText( "Very large scout mission completed by", true );
							newsItem.addTitleText( " " + armyName, false );
							difference = 20;
							maxResults = 12;
						}
						rs2 = stmt2.executeQuery( "SELECT count(*) FROM village WHERE x > " + ( x - difference ) + " AND x < " + ( x + difference ) + " AND y > " + ( y - difference ) + " AND y < " + ( y + difference ) );// + " AND NOT ruler_id = " + ruler_id );
						int total = 0;
						if( rs2.next() ) {
							total = rs2.getInt( "count(*)" );
						}
						
						AgesOfStrifeServer.log.debug( "Scouting mission complete, " + total + " possible villages." );
						//String tmp = "";
						if( total > maxResults ) {
							total = maxResults;
						}

						newsItem.addText( "Scouted from", true );
						newsItem.addText( ": <a href=\"../operations/map.php?x=" + ( x - 20 ) + "&y=" + ( y - 20 ) + "\">(" + x + "," + y + ")</a>.\n\n", false );
						int count = 0;
						rs2 = stmt2.executeQuery( "SELECT * FROM village WHERE x > " + ( x - difference ) + " AND x < " + ( x + difference ) + " AND y > " + ( y - difference ) + " AND y < " + ( y + difference ) + " ORDER BY RAND()" );// + " AND NOT ruler_id = " + ruler_id );
						while ( rs2.next() && count < total ) {
							rs3 = stmt3.executeQuery( "SELECT count(*) FROM scouted WHERE village_id = " + rs2.getInt( "village_id" ) + " AND ruler_id = " + ruler_id );
							rs3.next();
							if( rs3.getInt( "count(*)" ) == 0 ) {
								count ++;
							}
						}
						
						if( count == 0 ) {
							newsItem.addText( "All villages in this area are already discovered.", true );
						}
						else if ( count == 1 ){
							newsItem.addText( "Found one village.", true );
							newsItem.addText( "\n", false );
						}
						else {
							newsItem.addText( "Found", true );
							newsItem.addText( " " + count + " ", false );
							newsItem.addText( "villages", true );
							newsItem.addText( ".\n", false );
						}
						
						int i = 0;
						
						rs2.beforeFirst();
						while ( rs2.next() && i < total ) {
							rs3 = stmt3.executeQuery( "SELECT count(*) FROM scouted WHERE village_id = " + rs2.getInt( "village_id" ) + " AND ruler_id = " + ruler_id );
							rs3.next();
							if( rs3.getInt( "count(*)" ) == 0 ) {
								String village_name = rs2.getString( "name" );
								int village_x = rs2.getInt( "x" );
								int village_y = rs2.getInt( "y" );
								if( village_name == null ) {
									newsItem.addText( "Found an independent village at", true );
									newsItem.addText( " <a href=\"../operations/map.php?x=" + ( village_x - 20 ) + "&y=" + ( village_y - 20 ) + "\">(" + village_x + ", " + village_y + ")</a>.\n", false );
								}
								else {
									newsItem.addText( "Found a village called", true );
									newsItem.addText( " " + village_name + " ", false );
									newsItem.addText( "at", true );
									newsItem.addText( " <a href=\"../operations/map.php?x=" + ( village_x - 20 ) + "&y=" + ( village_y - 20 ) + "\">(" + village_x + ", " + village_y + ")</a>.\n", false );
								}
								stmtUpdate.execute( "INSERT INTO scouted ( village_id, ruler_id ) VALUES ( " + rs2.getInt( "village_id" ) + ", " + ruler_id + ")" );
								i ++;
							}
						}
						
						newsItem.insert( ruler_id, 0, turn, date );
					}
					stmtUpdate.execute( "UPDATE army SET mission = 0, mission_type = -1 WHERE army_id = " + army_id );
				}
				else {
					stmtUpdate.executeUpdate( "UPDATE army SET mission = " + mission + " WHERE army_id = " + army_id );
				}
			}
			else if( training == 0 && mission == 0 && fortified == 0 ) {
				rs2 = stmt2.executeQuery( "SELECT * " +
						"FROM army_orders " +
						"WHERE army_id = " + army_id + " AND rank = 0" );
				if( rs2.next() ) {
					AgesOfStrifeServer.log.debug( "Army with id: " + army_id + " has orders." );
					int order_type = rs2.getInt( "order_type" );
					int complete_turn = rs2.getInt( "complete_turn" );
					int army_order_id = rs2.getInt( "army_order_id" );
					double actual_x = rs.getDouble( "actual_x" );
					double actual_y = rs.getDouble( "actual_y" );
					int target_x = rs2.getInt( "order_value" );
					int target_y = rs2.getInt( "order_value2" );
					
					if( complete_turn > 0 && complete_turn <= turn ) { // current order is completed
						if( order_type == 1 ) { // move order, we need to reset the coordinates to remove rounding errors
							if( fatigue > 0 ) {
								actual_x = x = target_x;
								actual_y = y = target_y;
								stmtUpdate.executeUpdate( "UPDATE army " +
										"SET x = " + x + ", y = " + y + ", actual_x = " + x + ", actual_y = " + y + ", travel = 0, arrived_turn = " + turn + " " +
										"WHERE army_id = " + army_id );
								// If we arrived at an enemy village we need to send out a news item
								checkArmyLocation( army_id, ruler_id );
								moving = true;
							}
							else {
								stmtUpdate.execute( "UPDATE army_orders " +
										"SET complete_turn = complete_turn + 1 " +
										"WHERE army_order_id = " + army_order_id );
							}
						}
						if( order_type == 1 && moving || order_type == 2 ) {
							stmtUpdate.execute( "DELETE FROM army_orders WHERE army_order_id = " + army_order_id );
							rs3 = stmt3.executeQuery( "SELECT * FROM army_orders WHERE army_id = " + army_id + " AND rank > 0" );
							boolean lastOrder = true;
							while( rs3.next() ) {
								lastOrder = false;
								stmtUpdate.execute( "UPDATE army_orders SET rank = " + ( rs3.getInt( "rank" ) - 1 ) + " WHERE army_order_id = " + rs3.getInt( "army_order_id" ) );
							}
							
							if( lastOrder ) {
								String army_name = rs.getString( "name" );
								newsItem.clear();
								newsItem.addTitleText( "Our army", true );
								newsItem.addTitleText( " " + army_name + " ", false );
								newsItem.addTitleText( "has finished all orders", true );
								newsItem.addText( "One of our armies has finished all given orders.", true );
								newsItem.addText( "\n\n", false );
								newsItem.addText( "Army", true );
								newsItem.addText( ": <a href=\"../armies/army.php?name=" + army_name + "\" title=\"" + army_name + "\">" + army_name + "</a> ", false );
								newsItem.addText( "is currently at", true );
								newsItem.addText( " <a href=\"../operations/map.php?x=" + ( x - 20 ) + "&y=" + ( y - 20 ) + "\" title=\"", false );
								newsItem.addText( "To the map", true );
								newsItem.addText( "\">(" + x + ", " + y + ")</a>.", false );
								newsItem.insert( ruler_id, 0, turn, date );
							}
						}
					}
					else if( order_type == 1 ) { // move order
						int travel = -1;
						if( complete_turn == 0 ) { // start new move order
							travel = Utils.startTravel( rs3, stmt3, army_id, x, y, target_x, target_y, turn, date );
							if( travel != -1 ) { // only if the move is valid
								if( fatigue > 0 ) {
									complete_turn = turn + travel;
									int start_turn = turn;
									stmtUpdate.execute( "UPDATE army_orders SET complete_turn = " + complete_turn + ", start_turn = " + start_turn + " WHERE army_order_id = " + army_order_id );
									double travel_total = Math.sqrt( ( x - target_x ) * ( x - target_x ) + ( y - target_y ) * ( y - target_y ) );
									
									double total = travel;
									double part = ( total - travel ) / total;
									
									actual_x = x + ( target_x - x ) * part;
									actual_y = y + ( target_y - y ) * part;
									stmtUpdate.executeUpdate( "UPDATE army SET travel_total = " + travel_total + ", travel = 1, actual_x = " + actual_x + ", actual_y = " + actual_y + " WHERE army_id = " + army_id );
									moving = true;
								}
							}
						}
						// TODO: experimental setting, during the winter movement requires 2 supply
						else if( ( fatigue > 0 && season != 0 ) || ( season == 0 && fatigue > 1 ) ) {
							//double travel_total = rs.getDouble( "travel_total" );
							travel = rs2.getInt( "complete_turn" ) - turn;
							double total = rs2.getInt( "complete_turn" ) - rs2.getInt( "start_turn" );
							double part = /*travel_total * 1.0 -*/ ( total - travel ) / total;
							//System.out.println( "travel: " + travel + "\r\ntravel_total: " + travel_total + "\r\ntotal: " + total );
							//System.out.println( "target_y: " + target_y + "\r\npart: " + part + "\r\ny: " + y );
							
							actual_x = x + ( target_x - x ) * part;
							actual_y = y + ( target_y - y ) * part;
							stmtUpdate.executeUpdate( "UPDATE army SET actual_x = " + actual_x + ", actual_y = " + actual_y + " WHERE army_id = " + army_id );
							moving = true;
						}
						else {
							stmtUpdate.execute( "UPDATE army_orders " +
									"SET complete_turn = complete_turn + 1 " +
									"WHERE army_order_id = " + army_order_id );
						}
					}
					else if( order_type == 2 ) { // wait order
						stmtUpdate.execute( "UPDATE army " +
								"SET travel = 0 " +
								"WHERE army_id = " + army_id );
						if( complete_turn == 0 ) {
							int turns_to_wait = rs2.getInt( "order_value" );
							if( turns_to_wait == 1 ) {
								stmtUpdate.execute( "DELETE FROM army_orders WHERE army_order_id = " + army_order_id );
								rs3 = stmt3.executeQuery( "SELECT * FROM army_orders WHERE army_id = " + army_id + " AND rank > 0" );
								boolean lastOrder = true;
								while( rs3.next() ) {
									lastOrder = false;
									stmtUpdate.execute( "UPDATE army_orders SET rank = " + ( rs3.getInt( "rank" ) - 1 ) + " WHERE army_order_id = " + rs3.getInt( "army_order_id" ) );
								}
								
								if( lastOrder ) {
									String army_name = rs.getString( "name" );
									newsItem.clear();
									newsItem.addTitleText( "Our army", true );
									newsItem.addTitleText( " " + army_name + " ", false );
									newsItem.addTitleText( "has finished all orders", true );
									newsItem.addText( "One of our armies has finished all given orders.", true );
									newsItem.addText( "\n\n", false );
									newsItem.addText( "Army", true );
									newsItem.addText( ": <a href=\"../armies/army.php?name=" + army_name + "\" title=\"" + army_name + "\">" + army_name + "</a> ", false );
									newsItem.addText( "is currently at", true );
									newsItem.addText( " <a href=\"../operations/map.php?x=" + ( x - 20 ) + "&y=" + ( y - 20 ) + "\" title=\"", false );
									newsItem.addText( "To the map", true );
									newsItem.addText( "\">(" + x + ", " + y + ")</a>.", false );
									newsItem.insert( ruler_id, 0, turn, date );
								}
							}
							else {
								stmtUpdate.execute( "UPDATE army_orders SET complete_turn = " + ( turn + turns_to_wait - 1 ) + ", start_turn = " + ( turn - 1 ) + " WHERE army_order_id = " + army_order_id );
							}
						}
					}
					
					if( order_type == 1 ) { // if the current order type is or was move, check for villages around the army
						rs3 = stmt3.executeQuery( "SELECT * FROM village WHERE x > " + ( actual_x - 1 ) + " AND x < " + ( actual_x + 1 ) + " AND y > " + ( actual_y - 1 ) + " AND y < " + ( actual_y + 1 ) );
						// Go through all villages this army is passing
						while ( rs3.next() ) {
							newsItem.clear();
							newsItem.addTitleText( "Village spotted at", true );
							newsItem.addTitleText(  " (" + rs3.getInt( "x" ) + ", " + rs3.getInt( "y" ) + ")", false );
							String village_name = rs3.getString( "name" );
							int village_ruler = rs3.getInt( "ruler_id" );
							if( village_ruler != ruler_id ) {
								//int village_id = rs3.getInt( "village_id" );
								rs4 = stmt4.executeQuery( "SELECT count(*) FROM scouted WHERE village_id = " + rs3.getInt( "village_id" ) + " AND ruler_id = " + ruler_id );
								rs4.next();
								if( rs4.getInt( "count(*)" ) == 0 ) {
									if( village_name == null ) {
										newsItem.addText( "Found a new independent village at", true );
										newsItem.addText( " <a href=\"../operations/map.php?x=" + ( rs3.getInt( "x" ) - 20 ) + "&y=" + ( rs3.getInt( "y" ) - 20 ) + "\" title=\"", false );
										newsItem.addText( "Show location on map", true );
										newsItem.addText( "\">(" + rs3.getInt( "x" ) + ", " + rs3.getInt( "y" ) + ")</a>.\n", false );
									}
									else {
										newsItem.addText( "Found a new village called", true );
										newsItem.addText( " \"" + village_name + "\" ", false );
										newsItem.addText( "at", true );
										newsItem.addText( " <a href=\"../operations/map.php?x=" + ( rs3.getInt( "x" ) - 20 ) + "&y=" + ( rs3.getInt( "y" ) - 20 ) + "\" title=\"", false );
										newsItem.addText( "Show location on map", true );
										newsItem.addText( "\">(" + rs3.getInt( "x" ) + ", " + rs3.getInt( "y" ) + ")</a>.\n", false );
									}
									stmtUpdate.execute( "INSERT INTO scouted ( village_id, ruler_id ) VALUES ( " + rs3.getInt( "village_id" ) + ", " + ruler_id + ")" );
									newsItem.insert( ruler_id, 0, turn, date );
								}
							}
						}
					}
				}
				else if( army_travel > 0 ) {
					// Set army to not moving if it has no more orders and is still set to move
					stmtUpdate.execute( "UPDATE army " +
							"SET travel = 0 " +
							"WHERE army_id = " + army_id );
					// If we stopped at an enemy village we need to send out a news item
					checkArmyLocation( army_id, ruler_id );
				}
			}
			if( moving ) {
				if( season == 0 ) {
					fatigue -= 2;
				}
				else {
					fatigue --;
				}
			}
			else {
				int currentX = ( int ) Math.round( rs.getDouble( "actual_x" ) );
				int currentY = ( int ) Math.round( rs.getDouble( "actual_y" ) );
				rs2 = stmt2.executeQuery( "SELECT village_id, ruler_id, loyalty, loyal_to " +
						"FROM village " +
						"WHERE x = " + currentX + " AND y = " + currentY );
				if( rs2.next() ) {
					if( rs2.getInt( "ruler_id" ) == ruler_id && rs2.getInt( "loyal_to" ) == ruler_id && rs2.getInt( "loyalty" ) > 50 ) {
						if( season == 0 ) {
							fatigue += 2;
						}
						else {
							fatigue += 3;
						}
					}
					else {
						int villageRulerId = rs2.getInt( "ruler_id" );
						int loyalTo = rs2.getInt( "loyal_to" );
						int loyalty = rs2.getInt( "loyalty" );
						rs2 = stmt2.executeQuery( "SELECT faction_id " +
								"FROM faction_member " +
								"WHERE ruler_id = " + ruler_id + " AND invited = 0 AND requested = 0" );
						if( rs2.next() ) {
							int factionId = rs2.getInt( "faction_id" );
							rs2 = stmt2.executeQuery( "SELECT faction_id " +
									"FROM faction_member " +
									"WHERE ruler_id = " + villageRulerId + " AND invited = 0 AND requested = 0" );
							if( rs2.next() ) {
								if( rs2.getInt( "faction_id" ) == factionId && loyalTo == villageRulerId && loyalty > 50 ) {
									fatigue += 3;
								}
								else {
									fatigue ++;
								}
							}
							else {
								fatigue ++;
							}
						}
						else {
							fatigue ++;
						}
					}
				}
				else {
					fatigue ++;
				}
			}
			if( fatigue < 0 ) {
				fatigue = 0;
			}
			else if( fatigue > max_fatigue ) {
				fatigue = max_fatigue;
			}
			stmtUpdate.execute( "UPDATE army " +
					"SET fatigue = " + fatigue + " " +
					"WHERE army_id = " + army_id );
		}
		return score;
	}
	
	private void checkArmyLocation( int army_id, int ruler_id ) throws SQLException, NoSuchAlgorithmException {
		boolean hostile = true;
		String faction_name = "";
		rs4 = stmt4.executeQuery( "SELECT x, y, scout, infantry, cavalry, artillery, officer_id " +
				"FROM army " +
				"WHERE army_id = " + army_id );
		rs4.next();
		int x = rs4.getInt( "x" );
		int y = rs4.getInt( "y" );
		int scout = rs4.getInt( "scout" );
		int infantry = rs4.getInt( "infantry" );
		int cavalry = rs4.getInt( "cavalry" );
		int artillery = rs4.getInt( "artillery" );
		int officer_id = rs4.getInt( "officer_id" );
		// If this is not an invisible scout army
		if( !( scout == 1 && infantry == 0 && cavalry == 0 && artillery == 0 && officer_id == -1 ) ) {
			int attacked_faction = -1;
			rs4 = stmt4.executeQuery( "SELECT ruler_id, name, start_place " +
					"FROM village " +
					"WHERE x = " + x + " AND y = " + y );
			if( rs4.next() ) {
				// So the army arrived at a village
				int village_ruler_id = rs4.getInt( "ruler_id" );
				int start_place = rs4.getInt( "start_place" );
				String village_name = rs4.getString( "name" );
				
				if( village_ruler_id == ruler_id ) {
					hostile = false;
				}
				else {
					rs4 = stmt4.executeQuery( "SELECT faction.faction_id, name " +
							"FROM faction_member " +
							"JOIN faction ON faction.faction_id = faction_member.faction_id " +
							"WHERE ruler_id = " + ruler_id + " AND invited = 0 AND requested = 0" );
					if( rs4.next() ) { 
						// army owner is in a faction, need to check if the village owner is in the same faction
						int faction_id = rs4.getInt( "faction_id" );
						faction_name = rs4.getString( "name" );
						rs4 = stmt4.executeQuery( "SELECT faction_id " +
								"FROM faction_member " +
								"WHERE ruler_id = " + village_ruler_id + " AND invited = 0 AND requested = 0" );
						if( rs4.next() ) {
							if( faction_id == rs4.getInt( "faction_id" ) ) {
								hostile = false;
							}
							else {
								attacked_faction = rs4.getInt( "faction_id" );
							}
						}
					}
					else {
						rs4 = stmt4.executeQuery( "SELECT faction_id " +
								"FROM faction_member " +
								"WHERE ruler_id = " + village_ruler_id + " AND invited = 0 AND requested = 0" );
						if( rs4.next() ) {
							attacked_faction = rs4.getInt( "faction_id" );
						}
					}
				}
				
				if( hostile ) { // army is moving towards an enemy,
					// have to make sure the ruler beeing attacked gets a news item about it 
					// attacked ruler (and faction members) get under_attack flag
					
					if( attacked_faction != -1 ) {
						rs4 = stmt4.executeQuery( "SELECT count(*) FROM " +
								"faction_member " +
								"WHERE faction_id = " + attacked_faction + " AND requested = 0 AND invited = 0" );
						if( rs4.next() ) {
							int[] rulers4 = new int[ rs4.getInt( 1 ) ];
							rs4 = stmt4.executeQuery( "SELECT ruler_id FROM faction_member " +
									"WHERE faction_id = " + attacked_faction + " AND requested = 0 AND invited = 0" );
							int count = 0;
							while( rs4.next() ) {
								rulers4[count] = rs4.getInt( "ruler_id" );
								count ++;
							}
							
							for( int i = 0; i < count; i ++ ) {
								stmt4.execute( "UPDATE ruler SET under_attack = 1 WHERE ruler_id = " + rulers4[i] );
							}
						}
					}
					
					String ruler_name = "";
					boolean translateName = false;
					if( ruler_id != -1 ) {
						rs4 = stmt4.executeQuery( "SELECT name " +
								"FROM ruler " +
								"WHERE ruler_id = " + ruler_id );
						if( rs4.next() ) {
							ruler_name = rs4.getString( "name" );
						}
					}
					else {
						ruler_name = "Independent forces";
						translateName = true;
					}
					newsItem.clear();
					newsItem.addTitleText( "A hostile army has arrived at", true );
					newsItem.addTitleText( " " + village_name, false );
					newsItem.addText( "An army owned by", true );
					newsItem.addText( " ", false );
					newsItem.addText( ruler_name, translateName );
					newsItem.addText( " ", false );
					if( faction_name != "" ) {
						newsItem.addText( "from", true );
						newsItem.addText( " " + faction_name + " ", false );
					}
					newsItem.addText( "has arrived at our village", true );
					newsItem.addText( ": " + village_name + " ", false );
					newsItem.addText( "at", true );
					newsItem.addText( " <a href=\"../operations/map.php?x=" + ( x - 20 ) + "&y=" + ( y - 20 ) + "\">(" + x + ", " + y + ")</a>.\n", false );
					if( start_place == 1 ) {
						newsItem.addText( "We have 12 days left before they can loot our capital.", true );
					}
					newsItem.insert( village_ruler_id, 1, turn, date );
				}
			}
		}
	}
	
	/**
	 * @param ruler_id
	 * @param score
	 * @return
	 * @throws SQLException
	 * 
	 * This method handles unit transfers for armies which have been destroyed
	 */
	private long handleTransfer( int ruler_id, long score ) throws SQLException {
		rs = stmt.executeQuery( "SELECT * " +
				"FROM transfer " +
				"WHERE ruler_id = " + ruler_id + " AND complete_turn < " + ( turn - 2 ) );
		while ( rs.next() ) {
			//int armyId = rs.getInt( "army_id" );
			int scout = rs.getInt( "scouts" );
			int infantry = rs.getInt( "infantry" );
			int cavalry = rs.getInt( "cavalry" );
			int artillery = rs.getInt( "artillery" );
			
			/*rs2 = stmt2.executeQuery( "SELECT count(*) " +
					"FROM army " +
					"WHERE army_id = " + armyId );
			rs2.next();
			if( rs2.getInt( 1 ) == 0 ) {*/
				stmtUpdate.execute( "UPDATE ruler " +
						"SET scouts = scouts + " + scout + ", " +
							"infantry = infantry + " + infantry + ", " +
							"cavalry = cavalry + " + cavalry + ", " +
							"artillery = artillery + " + artillery + " " +
						"WHERE ruler_id = " + ruler_id );
			/*}
			else {
				AgesOfStrifeServer.log.warn( "An army transfer has expired but it's army still exists: army = " + armyId + ", ruler = " + ruler_id );
			}*/
			stmtUpdate.execute( "DELETE FROM transfer WHERE transfer_id = " + rs.getInt( "transfer_id" ) );
		}
		return score;
	}	
	
	private void updateRaces() throws SQLException, NoSuchAlgorithmException {
		rs = stmt.executeQuery( "SELECT * " +
				"FROM races " +
				"WHERE turn >= " + turn + " " +
				"ORDER BY turn DESC " +
				"LIMIT 1" );
		if( rs.next() ) { // There is a race this turn
			int race_turn = rs.getInt( "turn" );
			if( race_turn == turn ) {
				int prizes = rs.getInt( "prizes" );
				int race_id = rs.getInt( "race_id" );
				rs = stmt.executeQuery( "SELECT count(*) " +
						"FROM race_teams" );
				int totalTeams = 0;
				if( rs.next() ) {
					totalTeams = rs.getInt( 1 );
				}
				AgesOfStrifeServer.log.debug( "A race is going on with " + totalTeams + " teams." );
				rs2 = stmt2.executeQuery( "SELECT * " +
						"FROM race_teams " +
						"ORDER BY RAND()" );
				while( rs2.next() ) {
					int race_team_id = rs2.getInt( "race_team_id" );
					int intelligence = rs2.getInt( "intelligence" );
					int acceleration = rs2.getInt( "acceleration" );
					int stamina = rs2.getInt( "stamina" );
					int strength = rs2.getInt( "strength" );
					int agility = rs2.getInt( "agility" );
					double morale = rs2.getInt( "morale" );

                    int speed = 0;
                    for(int i = 10; i > 0 && strength > 0; i--) {
                        double chance = 1 + (Math.random() * Math.pow(agility, 2))/10;
                        double strength_decrease = Math.max(0, (50 - Math.pow(stamina,2)) / (i * chance) - i);
                        strength = (int) Math.round(Math.max(0, strength - strength_decrease));
                        speed += strength;
                    }

					speed += Math.pow(2, acceleration);
					double chance = Math.random() * (0.5 - morale * 0.325);
                                        double intelligence_decrease = Math.max(0, chance * (speed - Math.pow(intelligence, 2)));
					speed = ( int ) Math.round(Math.max(0, speed - intelligence_decrease));
					stmtUpdate.execute( "INSERT INTO race_history ( race_id, race_team_id, speed ) VALUES ( " + race_id + ", " + race_team_id + ", " + speed + " )" );
				}
				rs2 = stmt2.executeQuery( "SELECT race_history.*, race_teams.morale " +
						"FROM race_history " +
						"JOIN race_teams ON race_teams.race_team_id = race_history.race_team_id " +
						"WHERE race_id = " + race_id + " " +
						"ORDER BY speed DESC" );
				int winner_id = -1;
				int rank = 1;
				String winnerName = "";
				while( rs2.next() ) {
					int race_team_id = rs2.getInt( "race_team_id" );
					int race_history_id = rs2.getInt( "race_history_id" );
					int won = 0;
					double morale = rs2.getDouble( "morale" );
					String number = "";
					double chance;
					AgesOfStrifeServer.log.debug( "Rank: " + rank + ", morale before race: " + morale );
					double tmp = 0;
					morale += ( tmp = ( ( 0.75 - ( double ) rank / ( double ) totalTeams ) - 0.20 ) * 0.1/* + 0.005*/ );
					if( morale > 1 ) {
						morale = 1;
					}
					else if( morale < 0.05 ) {
						morale = 0.05;
					}
					
					AgesOfStrifeServer.log.debug( "Morale after race: " + morale );
					AgesOfStrifeServer.log.debug( "Morale difference: " + tmp );
					if( rank == 1 ) {
						won = ( int ) Math.round( prizes * 0.6 );
						number = "1st";
						winner_id = race_team_id;
						chance = 0.56;
					}
					else  if( rank == 2 ) {
						won = ( int ) Math.round( prizes * 0.3 );
						number = "2nd";
						chance = 0.62;
					}
					else if ( rank == 3 ) {
						won = ( int ) Math.round( prizes * 0.1 );
						number = "3rd";
						chance = 0.68;
					}
					else if( rank > totalTeams - 5 ) {
						chance = Math.pow(1.3, rank - totalTeams + 4);
					}
					else {
						chance = 0.74;
					}
					
					if( won > 0 ) {
						rs3 = stmt3.executeQuery( "SELECT faction.faction_id, faction.gold, race_teams.name " +
								"FROM faction " +
								"JOIN race_teams ON faction.faction_id = race_teams.faction_id " +
								"WHERE race_team_id = " + race_team_id );
						if( rs3.next() ) {
							int gold = rs3.getInt( "gold" );
							int faction_id = rs3.getInt( "faction_id" );
							String name = rs3.getString( "name" );
							if( rank == 1 ) {
								winnerName = name;
							}
							stmtUpdate.execute( "UPDATE faction " +
									"SET gold = " + ( gold + won ) + " " +
									"WHERE faction_id = " + faction_id );
							
							newsItem.clear();
							newsItem.addTitleText( "Horse race team", true );
							newsItem.addTitleText( " " + name + " ", false );
							newsItem.addTitleText( "came in", true );
							newsItem.addTitleText( " ", false );
							newsItem.addTitleText( number, true );
							newsItem.addText( "Our factions horse race team came in", true );
							newsItem.addText( " ", false );
							newsItem.addText( number, true );
							newsItem.addText( ".\n", false );
							newsItem.addText( "Our faction has received", true );
							newsItem.addText( " <strong class=\"gold\">" + Utils.formatNumber( "" + won ) + "</strong> ", false );
							newsItem.addText( "gold", true );
							newsItem.addText( ".", false );
							rs4 = stmt4.executeQuery( "SELECT ruler_id " +
									"FROM faction_member " +
									"WHERE invited = 0 AND requested = 0 AND faction_id = " + faction_id );
							while( rs4.next() ) {
								newsItem.insert(rs4.getInt( "ruler_id" ), 2, turn, date );
							}
						}
					}
					int agi = ( int ) Math.round( Math.random() * chance );
					int str = ( int ) Math.round( Math.random() * chance );
					int acc = ( int ) Math.round( Math.random() * chance );
					int sta = ( int ) Math.round( Math.random() * chance );
					int intel = ( int ) Math.round( Math.random() * chance );
					
					rs4 = stmt4.executeQuery( "SELECT * " +
							"FROM race_teams " +
							"WHERE race_team_id = " + race_team_id );
					if( rs4.next() ) {
						stmtUpdate.execute( "UPDATE race_teams SET agility = " + ( rs4.getInt( "agility" ) + agi ) + 
								", strength = " + ( rs4.getInt( "strength" ) + str ) + 
								", acceleration = " + ( rs4.getInt( "acceleration" ) + acc ) + 
								", stamina = " + ( rs4.getInt( "stamina" ) + sta ) + 
								", intelligence = " + ( rs4.getInt( "intelligence" ) + intel ) + 
								", morale = " + morale + 
								" WHERE race_team_id = " + race_team_id );
					}
					stmtUpdate.execute( "UPDATE race_history " +
							"SET rank = " + rank + ", gold_won = " + won + " " +
							"WHERE race_history_id = " + race_history_id );
					rank ++;
				}
				stmtUpdate.execute( "UPDATE races " +
						"SET date = '" + date + "' " +
						"WHERE race_id = " + race_id );
				
				rs2 = stmt2.executeQuery( "SELECT SUM(gold) FROM race_bets WHERE race_id = " + race_id );
				long totalGold = 0;
				if( rs2.next() ) {
					totalGold = rs2.getLong( 1 );
				}
				
			 	rs2 = stmt2.executeQuery( "SELECT count(*) " +
			 			"FROM race_history " +
			 			"JOIN races ON races.race_id = race_history.race_id " +
			 			"WHERE race_team_id = " + winner_id + " AND turn < " + turn );
			 	int total_races = 0;
			 	if( rs2.next() ) {
			 		total_races = rs2.getInt( 1 );
			 	}
				
			 	int wins = 0;
				double payout = 0;
			 	
				if( total_races > 0 ) {
				 	rs2 = stmt2.executeQuery( "SELECT count(*) " +
				 			"FROM race_history " +
				 			"JOIN races ON races.race_id = race_history.race_id " +
				 			"WHERE rank = 1 AND race_team_id = " + winner_id + " AND turn < " + turn );
				 	if( rs2.next() ) {
				 		wins = rs2.getInt( 1 );
				 	}

                    payout = Math.pow(1.1, total_races/Math.max(1, wins));
				}
				else {
					payout = 2;
				}
                                
				long paidOut = 0;
				
				rs2 = stmt2.executeQuery( "SELECT race_bets.*, race_teams.name FROM race_bets JOIN race_teams ON race_bets.race_team_id = race_teams.race_team_id WHERE race_id = " + race_id );
				while( rs2.next() ) {
					int race_team_id = rs2.getInt( "race_team_id" );
					int race_bet_id = rs2.getInt( "race_bet_id" );
					int gold = rs2.getInt( "gold" );
					int ruler_id = rs2.getInt( "ruler_id" );
					int won = 0;
					if( race_team_id == winner_id ) { // winners
						rs3 = stmt3.executeQuery( "SELECT SUM(gold) FROM race_bets WHERE race_id = " + race_id + " AND ruler_id = " + ruler_id );
						rs3.next();
						int totalBets = rs3.getInt( 1 );
						won = ( int ) Math.round( gold * payout );
						String name = rs2.getString( "name" );
						paidOut += won;
						stmtUpdate.execute( "UPDATE ruler SET gold = gold + " + won + " WHERE ruler_id = " + ruler_id );
						newsItem.clear();
						newsItem.addTitleText( "Payout for your bet on", true );
						newsItem.addTitleText( " " + name, false );

						newsItem.addText( "You put a bet of", true );
						newsItem.addText( " <strong class=\"gold\">" + Utils.formatNumber( "" + gold ) + "</strong> ", false );
						newsItem.addText( "gold", true );
						if( totalBets != gold ) {
							newsItem.addText( ", ", false );
							newsItem.addText( "out of", true );
							newsItem.addText( " <strong class=\"gold\">" + Utils.formatNumber( "" + totalBets ) + "</strong>", false );
							newsItem.addText( "gold you bet in total, on this race", true );
						}
						else {
							newsItem.addText( " ", false );
							newsItem.addText( "on this race", false );
						}
						newsItem.addText( ".\n", false );
						newsItem.addText( "At a payout of", true );
						newsItem.addText( " " + ( ( int ) Math.round( payout * 100.0 ) * 0.01 ) + ":1, ", false );
						newsItem.addText( "you won", true );
						newsItem.addText( " <strong class=\"gold\">" + Utils.formatNumber( "" + won ) + "</strong> ", false );
						newsItem.addText( "gold", true );
						newsItem.addText( ".", false );
						newsItem.insert( ruler_id, 2, turn, date );
					}
					stmtUpdate.execute( "UPDATE race_bets SET payout = " + won + " WHERE race_bet_id = " + race_bet_id );
				}
				
				// Let the world know they could have made big money! :)
				if( payout > 10 ) {
				 	rs2 = stmt2.executeQuery( "SELECT name " +
				 			"FROM race_teams " +
				 			"WHERE race_team_id = " + winner_id );
				 	if( rs2.next() ) {
				 		winnerName = rs2.getString( "name" );
				 	}
					
					String title = winnerName + " has won the horse race";
					String text = "Because team " + winnerName + " was the underdog there was a payout of " + ( ( ( int ) Math.round( payout * 100.0 ) ) * 0.01 ) + ":1!\r\n\r\n";
					
					if( paidOut == 0 ) {
						text += "No one put a bet on " + winnerName + " though.\r\nBets were placed for a total of <strong class=\\\"gold\\\">" + Utils.formatNumber( "" + totalGold ) + "</strong> gold, 60% of this will be used as prize gold in the next race!";
					}
					else {
						text += "Congratulations to all those who bet on the winning team this race!\r\nA total of <strong class=\\\"gold\\\">" + Utils.formatNumber( "" + paidOut ) + "</strong> gold was paid out to the betters.";
					}
					
					stmtUpdate.execute( "INSERT INTO history " +
							"( title, text, ruler_id, turn, date, visible ) " +
							"VALUES ( '" + title + "', '" + text + "', -1, " + turn + ", '" + date + "', 1 )" );
					rs = stmt.executeQuery( "SELECT history_id " +
							"FROM history " +
							"WHERE title = '" + title + "' AND text = '" + text + "' AND ruler_id = -1 AND turn = " + turn + " AND date = '" + date + "' " +
							"LIMIT 1" );
					int history_id = -1;
					if( rs.next() ) {
						history_id = rs.getInt( "history_id" );
					}
					Utils.notifyOfHistory( rs, stmt, history_id );
				}
				
				scheduleNewRace( totalGold - paidOut );
			}
		}
		else {
			rs = stmt.executeQuery( "SELECT count(*) FROM race_teams" );
			if( rs.next() && rs.getInt( 1 ) > 1 ) { // schedule a new race, none scheduled yet
				scheduleNewRace( 0 );
			}
		}
	}
	
	private void scheduleNewRace( long startGold ) throws SQLException {
		if( startGold > 0 ) {
			startGold *= 0.6;
		}
		else {
			startGold = 0;
		}
		startGold += 100;
		double interval = 24;
		int nextTurn = ( int ) ( interval * ( Math.floor( turn / interval ) + 1 ) );
		stmtUpdate.execute( "INSERT INTO races ( date, turn, prizes ) VALUES ( '', " + nextTurn + ", " + startGold + " )" );
	}
	
	private void updateFollowingFatigue() throws SQLException {
		rs = stmt.executeQuery( "SELECT army_id, max_fatigue " +
				"FROM army " +
				"WHERE ( SELECT count(*) FROM army AS army2 WHERE army2.follow = army.army_id ) > 0" );
		while( rs.next() ) {
			int armyId = rs.getInt( "army_id" );
			int max_fatigue = rs.getInt( "max_fatigue" );
			rs2 = stmt2.executeQuery( "SELECT max_fatigue " +
					"FROM army " +
					"WHERE follow = " + armyId );
			while( rs2.next() ) {
				if( rs2.getInt( "max_fatigue" ) < max_fatigue ) {
					max_fatigue = rs2.getInt( "max_fatigue" );
				}
			}
			stmtUpdate.execute( "UPDATE army " +
					"SET max_fatigue = " + max_fatigue + " " +
					"WHERE army_id = " + armyId );
			stmtUpdate.execute( "UPDATE army " +
					"SET max_fatigue = " + max_fatigue + " " +
					"WHERE follow = " + armyId );
			stmtUpdate.execute( "UPDATE army " +
					"SET fatigue = " + max_fatigue + " " +
					"WHERE ( follow = " + armyId + " OR army_id = " + armyId + " ) AND fatigue > max_fatigue" );
		}
	}
	
	private void checkForTaskProgress() throws SQLException {
		rs = stmt.executeQuery( "SELECT * " +
				"FROM ruler_task " +
				"JOIN tasks ON tasks.task_id = ruler_task.task_id " +
				"WHERE completed = 0 AND finished = 0 AND ( " +
					"required_scouts != 0 OR required_infantry != 0 OR required_cavalry != 0 OR required_artillery != 0 OR " +
					"required_gold != 0 OR required_iron != 0 OR required_coal != 0 OR required_recruits != 0 OR " +
					"required_population != 0 OR required_villages != 0 OR required_building != 0 OR required_upgrade != 0 OR required_food != 0 )" );
		while( rs.next() ) {
			int taskId = rs.getInt( "task_id" );
			int rulerId = rs.getInt( "ruler_id" );
			int requiredScouts = rs.getInt( "required_scouts" );
			int requiredInfantry = rs.getInt( "required_infantry" );
			int requiredCavalry = rs.getInt( "required_cavalry" );
			int requiredArtillery = rs.getInt( "required_artillery" );
			int requiredGold = rs.getInt( "required_gold" );
			int requiredIron = rs.getInt( "required_iron" );
			int requiredCoal = rs.getInt( "required_coal" );
			int requiredRecruits = rs.getInt( "required_recruits" );
			int requiredPopulation = rs.getInt( "required_population" );
			int requiredVillages = rs.getInt( "required_villages" );
			int requiredBuilding = rs.getInt( "required_building" );
			int requiredUpgrade = rs.getInt( "required_upgrade" );
			int requiredAmount = rs.getInt( "required_amount" );
			int requiredFood = rs.getInt( "required_food" );

			long total = 0;
			int finished = 0;
			
			if( requiredScouts > 0 ) {
				rs2 = stmt2.executeQuery( "SELECT SUM(scout) " +
						"FROM army " +
						"WHERE ruler_id = " + rulerId );
				if( rs2.next() ) {
					total = rs2.getInt( 1 );
				}
				if( total >= requiredScouts ) {
					finished = 1;
				}
			}
			if( requiredInfantry > 0 ) {
				rs2 = stmt2.executeQuery( "SELECT SUM(infantry) " +
						"FROM army " +
						"WHERE ruler_id = " + rulerId );
				if( rs2.next() ) {
					total = rs2.getInt( 1 );
				}
				if( total >= requiredInfantry ) {
					finished = 1;
				}
			}
			if( requiredCavalry > 0 ) {
				rs2 = stmt2.executeQuery( "SELECT SUM(cavalry) " +
						"FROM army " +
						"WHERE ruler_id = " + rulerId );
				if( rs2.next() ) {
					total = rs2.getInt( 1 );
				}
				if( total >= requiredCavalry ) {
					finished = 1;
				}
			}
			if( requiredArtillery > 0 ) {
				rs2 = stmt2.executeQuery( "SELECT SUM(artillery) " +
						"FROM army " +
						"WHERE ruler_id = " + rulerId );
				if( rs2.next() ) {
					total = rs2.getInt( 1 );
				}
				if( total >= requiredArtillery ) {
					finished = 1;
				}
			}

			if( requiredGold > 0 ) {
				rs2 = stmt2.executeQuery( "SELECT gold " +
						"FROM ruler " +
						"WHERE ruler_id = " + rulerId );
				if( rs2.next() ) {
					total = rs2.getInt( 1 );
				}
				if( total >= requiredGold ) {
					finished = 1;
				}
			}
			if( requiredIron > 0 ) {
				rs2 = stmt2.executeQuery( "SELECT iron " +
						"FROM ruler " +
						"WHERE ruler_id = " + rulerId );
				if( rs2.next() ) {
					total = rs2.getInt( 1 );
				}
				if( total >= requiredIron ) {
					finished = 1;
				}
			}
			if( requiredCoal > 0 ) {
				rs2 = stmt2.executeQuery( "SELECT coal " +
						"FROM ruler " +
						"WHERE ruler_id = " + rulerId );
				if( rs2.next() ) {
					total = rs2.getInt( 1 );
				}
				if( total >= requiredCoal ) {
					finished = 1;
				}
			}
			if( requiredFood > 0 ) {
				rs2 = stmt2.executeQuery( "SELECT food " +
						"FROM ruler " +
						"WHERE ruler_id = " + rulerId );
				if( rs2.next() ) {
					total = rs2.getInt( 1 );
				}
				if( total >= requiredFood ) {
					finished = 1;
				}
			}
			if( requiredRecruits > 0 ) {
				rs2 = stmt2.executeQuery( "SELECT recruits " +
						"FROM ruler " +
						"WHERE ruler_id = " + rulerId );
				if( rs2.next() ) {
					total = rs2.getInt( 1 );
				}
				if( total >= requiredRecruits ) {
					finished = 1;
				}
			}

			if( requiredPopulation > 0 ) {
				rs2 = stmt2.executeQuery( "SELECT SUM(workforce) " +
						"FROM village " +
						"WHERE ruler_id = " + rulerId );
				if( rs2.next() ) {
					total = ( int ) ( rs2.getInt( 1 ) * 1.666666666667 );
				}
				if( total >= requiredPopulation ) {
					finished = 1;
				}
			}

			if( requiredVillages > 0 ) {
				rs2 = stmt2.executeQuery( "SELECT count(*) " +
						"FROM village " +
						"WHERE ruler_id = " + rulerId );
				if( rs2.next() ) {
					total = rs2.getInt( 1 );
				}
				if( total >= requiredVillages ) {
					finished = 1;
				}
			}

			if( requiredBuilding > 0 ) {
				rs2 = stmt2.executeQuery( "SELECT SUM(ammount) " +
						"FROM village_buildings " +
						"JOIN village ON village.village_id = village_buildings.village_id " +
						"WHERE ruler_id = " + rulerId + " AND building_id = " + requiredBuilding );
				if( rs2.next() ) {
					total = rs2.getInt( 1 );
				}
				if( total >= requiredAmount ) {
					finished = 1;
				}
			}
			
			if( requiredUpgrade > 0 ) {
				rs2 = stmt2.executeQuery( "SELECT count(*) " +
						"FROM upgrade_status " +
						"WHERE ruler_id = " + rulerId + " AND achieved = 1 AND upgrade_id = " + requiredUpgrade );
				if( rs2.next() ) {
					total = rs2.getInt( 1 );
				}
				if( total >= 1 ) {
					finished = 1;
				}
			}
			
			if( finished == 1 ) {
				stmtUpdate.execute( "UPDATE ruler_task " +
						"SET finished = 1, updated = 1 " +
						"WHERE ruler_id = " + rulerId + " AND task_id = " + taskId );
			}
		}
	}
	
	private void updateSpotlightVillage() throws SQLException, NoSuchAlgorithmException {
		rs = stmt.executeQuery( "SELECT spotlight_village_id, spotlight_type " +
				"FROM game" );
		rs.next();
		int type = rs.getInt( "spotlight_type" ); 
		int villageId = rs.getInt( "spotlight_village_id" ); 
		if( villageId != -1 ) {
			type ++;
			if( type > 3 ) {
				type = 0;
			}
		}
		String title = "";
		String reason = "";
		int random = ( int ) Math.round( Math.random() * 4 );
		
		if( type == 0 ) {
			// Population
			title = "A village with a high <strong class=\\\"population\\\">population</strong>";
			reason = "because of its high <strong class=\"population\">population</strong>";
			rs = stmt.executeQuery( "SELECT village.name, village.village_id, ruler.ruler_id, user_id " +
					"FROM village " +
					"JOIN ruler ON village.ruler_id = ruler.ruler_id " +
					"WHERE village.ruler_id != -1 " +
					"ORDER BY population DESC " +
					"LIMIT 5" );
		}
		else if( type == 1 ) {
			// Coal
			title = "A village with great <strong class=\\\"coal\\\">coal</strong> extraction";
			reason = "because of its high <strong class=\"coal\">coal</strong> extaction";
			rs = stmt.executeQuery( "SELECT village.name, village.village_id, ruler.ruler_id, user_id " +
					"FROM village " +
					"JOIN ruler ON village.ruler_id = ruler.ruler_id " +
					"WHERE village.ruler_id != -1 AND village.coal_income > 0 " +
					"ORDER BY village.coal_income DESC " +
					"LIMIT 5" );
		}
		else if( type == 2 ) {
			// Food
			title = "A village with great <strong class=\\\"food\\\">food</strong> production";
			reason = "because of its high <strong class=\"food\">food</strong> production";
			rs = stmt.executeQuery( "SELECT village.name, village.village_id, ruler.ruler_id, user_id " +
					"FROM village " +
					"JOIN ruler ON village.ruler_id = ruler.ruler_id " +
					"WHERE village.ruler_id != -1 AND village.food_income > 0 " +
					"ORDER BY village.food_income DESC " +
					"LIMIT 5" );
		}
		else {
			// Iron
			title = "A village with great <strong class=\\\"iron\\\">iron</strong> extraction";
			reason = "because of its high <strong class=\"iron\">iron</strong> extaction";
			rs = stmt.executeQuery( "SELECT village.name, village.village_id, ruler.ruler_id, user_id " +
					"FROM village " +
					"JOIN ruler ON village.ruler_id = ruler.ruler_id " +
					"WHERE village.ruler_id != -1 AND village.iron_income > 0 " +
					"ORDER BY village.iron_income DESC " +
					"LIMIT 5" );
		}
		
		int counter = 0;
		boolean noChanges = false;
		while( counter <= random && !noChanges ) {
			if( rs.next() ) {
				counter ++;
			}
			else {
				noChanges = true;
			}
		}
		
		if( !noChanges ) {
			String villageTitle = rs.getString( 1 );
			villageId = rs.getInt( 2 );
			int rulerId = rs.getInt( 3 );
			stmtUpdate.execute( "UPDATE game " +
					"SET spotlight_village_id = " + villageId + ", spotlight_village_title = '" + title + "', spotlight_type = " + type );
			stmtUpdate.execute( "UPDATE users " +
					"SET promotion_points = promotion_points + 100 " +
					"WHERE user_id = " + rs.getInt( 4 ) );
			stmtUpdate.execute( "INSERT INTO vote_reward " +
					"( `user_id`, `timestamp`, `turn`, `site`, `reward` ) " +
					"VALUES( " + rs.getInt( 4 ) + ", " + ( System.currentTimeMillis() / 1000 ) + ", " + turn + ", 'www.agesofstrife.com', 100 )" );
			newsItem.clear();
			newsItem.addTitleText( villageTitle + " ", false );
			newsItem.addTitleText( "has been put in the spotlight", true );
			newsItem.addText( villageTitle + " ", false );
			newsItem.addText( "has been put in the spotlight", true );
			newsItem.addText( " ", false );
			newsItem.addText( reason, true );
			newsItem.addText( ".\n", false );
			newsItem.addText( "You can see it on the index page when you log out.", true );
			newsItem.addText( "\n", false );
			newsItem.addText( "You received 100 promotion points as a reward.", true );
			newsItem.insert( rulerId, 2, turn, date );
		}
		else {
			stmtUpdate.execute( "UPDATE game " +
					"SET spotlight_type = " + type );
		}
	}
	
	private void storePremiumStats() throws SQLException {
		rs = stmt.executeQuery( "SELECT ruler_id, score, experience, food, coal, iron, gold, recruits, scouts, infantry, cavalry, artillery, warrior_points, economy_points " +
				"FROM ruler " +
				"JOIN users ON users.user_id = ruler.user_id " +
				"WHERE premium > 0" );
		while( rs.next() ) {
			int rulerId = rs.getInt( "ruler_id" );
			long score = rs.getLong( "score" );
			long battleScore = rs.getLong( "experience" );
			long economyPoints = rs.getLong( "economy_points" );
			long warPoints = rs.getLong( "warrior_points" );
			long resourceScore = rs.getLong( "food" ) + rs.getLong( "coal" ) * 2 + rs.getLong( "iron" ) * 3 + rs.getLong( "gold" ) * 5 + rs.getLong( "recruits" );
			rs2 = stmt2.executeQuery( "SELECT SUM( scout ), SUM( infantry ), SUM( cavalry ), SUM( artillery ) " +
					"FROM army " +
					"WHERE ruler_id = " + rulerId );
			rs2.next();
			long armyScore = rs2.getLong( 1 ) * 32 + rs2.getLong( 2 ) * 48 + rs2.getLong( 3 ) * 256 + rs2.getLong( 4 ) * 400; 
			armyScore += rs.getLong( "scouts" ) * 32 + rs.getLong( "infantry" ) * 48 + rs.getLong( "cavalry" ) * 256 + rs.getLong( "artillery" ) * 400; 
			rs2 = stmt2.executeQuery( "SELECT SUM( scouts ), SUM( infantry ), SUM( cavalry ), SUM( artillery ) " +
					"FROM transfer " +
					"WHERE ruler_id = " + rulerId );
			rs2.next();
			armyScore += rs2.getLong( 1 ) * 32 + rs2.getLong( 2 ) * 48 + rs2.getLong( 3 ) * 256 + rs2.getLong( 4 ) * 400;

			rs2 = stmt2.executeQuery( "SELECT count( * ) " +
					"FROM ruler " +
					"WHERE score > " + score );
			rs2.next();
			int rank = rs2.getInt( 1 ) + 1;

			rs2 = stmt2.executeQuery( "SELECT count( * ) " +
					"FROM ruler " +
					"WHERE experience > " + battleScore );
			rs2.next();
			int battleRank = rs2.getInt( 1 ) + 1;

			rs2 = stmt2.executeQuery( "SELECT count( * ) " +
					"FROM ruler " +
					"WHERE warrior_points > " + warPoints );
			rs2.next();
			int warRank = rs2.getInt( 1 ) + 1;

			rs2 = stmt2.executeQuery( "SELECT count( * ) " +
					"FROM ruler " +
					"WHERE economy_points > " + economyPoints );
			rs2.next();
			int economyRank = rs2.getInt( 1 ) + 1;
			
			stmtUpdate.execute( "INSERT INTO premium_stats " +
					"( `ruler_id`, `type`, `value`, `description`, `turn` ) " +
					"VALUES ( " + rulerId + ", 1, " + score + ", 'Score', " + turn + " )," +
					"( " + rulerId + ", 2, " + battleScore + ", 'Battle score', " + turn + " )," +
					"( " + rulerId + ", 3, " + resourceScore + ", 'Resource score', " + turn + " )," +
					"( " + rulerId + ", 4, " + armyScore + ", 'Army score', " + turn + " ), " +
					"( " + rulerId + ", 5, " + rank + ", 'Score rank', " + turn + " )," +
					"( " + rulerId + ", 6, " + battleRank + ", 'Battle rank', " + turn + " )," +
					"( " + rulerId + ", 7, " + economyPoints + ", 'Economy points', " + turn + " )," +
					"( " + rulerId + ", 8, " + warPoints + ", 'War points', " + turn + " )," +
					"( " + rulerId + ", 9, " + economyRank + ", 'Economy rank', " + turn + " )," +
					"( " + rulerId + ", 10, " + warRank + ", 'War rank', " + turn + " )" );
		}
	}
	
	private void lowOnPremiumWarning() throws SQLException, NoSuchAlgorithmException {
		rs = stmt.executeQuery( "SELECT ruler_id " +
				"FROM ruler " +
				"JOIN users ON users.user_id = ruler.user_id " +
				"WHERE premium = 24" );
		while( rs.next() ) {
			int rulerId = rs.getInt( "ruler_id" );
			newsItem.clear();
			newsItem.addTitleText( "Almost out of premium turns", true );
			newsItem.addText( "You only have 24 premium turns left, when you run out of premium turns all premium features are going to stop working.", true );
			newsItem.addText( "\n", false );
			newsItem.addText( "You can buy some new premium turns at the premium turns shop to prevent this from happening.", true );
			newsItem.addText( "\n", false );
			newsItem.addText( "To buy premium turns, click", true );
			newsItem.addText( " <a href=\"../global/shop.php\">", false );
			newsItem.addText( "here", true );
			newsItem.addText( "</a>.\n\n", false );
			newsItem.addText( "Even if you run out of premium turns all your premium settings will be remembered,\nso as soon as you get some premium turns again they will be back to your preference.", true );
			newsItem.insert( rulerId, 2, turn, date );
		}
	}
	
	private void updateNewBattlescore() throws SQLException, NoSuchAlgorithmException {
		rs = stmt.executeQuery( "SELECT ruler_id, experience, experience_before " +
				"FROM ruler " +
				"WHERE experience * 0.001 * ( experience - experience_before ) > 250" );
		while( rs.next() ) {
			int rulerId = rs.getInt( "ruler_id" );
			long newBattlescore = ( long ) ( ( ( rs.getLong( "experience" ) * 0.001 ) + rs.getLong( "experience" ) - rs.getLong( "experience_before" ) ) * 0.2 );
			
			int infantry = 0;
			int cavalry = 0;
			int artillery = 0;
			
			if( newBattlescore < 45000 ) {
				if( newBattlescore <= 48 ) {
					newBattlescore = 48;
				}
				infantry = ( int ) Math.floor( newBattlescore / 48 );
			}
			else {
				infantry = cavalry = artillery = ( int ) ( newBattlescore * 0.33333333333333 );
				infantry = ( int ) Math.floor( infantry / 48 );
				cavalry = ( int ) Math.floor( cavalry / 256 );
				artillery = ( int ) Math.floor( artillery / 400 );
			}
			
			stmtUpdate.execute( "UPDATE ruler " +
					"SET infantry = infantry + " + infantry + ", cavalry = cavalry + " + cavalry + ", artillery = artillery + " + artillery + ", experience_before = experience " +
					"WHERE ruler_id = " + rulerId );
			
			newsItem.clear();
			newsItem.addTitleText( "New volunteers joined your reserves", true );
			newsItem.addText( "The battlescore you gained has not gone unnoticed, the following volunteers joined up with your reserves.", true );
			newsItem.addText( "\n\n<table class=\"news-table\"><tr><th>", false );
			newsItem.addText( "Unit", true );
			newsItem.addText( "</th><th>", false );
			newsItem.addText( "Amount", true );
			newsItem.addText( "</th></tr><tr><td>", false );
			newsItem.addText( "Infantry", true );
			newsItem.addText( ":</td><td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + infantry ) + "</strong></td></tr><tr><td>", false );
			newsItem.addText( "Cavalry", true );
			newsItem.addText( ":</td><td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalry ) + "</strong></td></tr><tr><td>", false );
			newsItem.addText( "Artillery", true );
			newsItem.addText( ":</td><td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + artillery ) + "</strong></td></tr></table>", false );
			newsItem.insert( rulerId, 0, turn, date );
		}
	}
	
	private void militiaLookingForAFight() throws SQLException, NoSuchAlgorithmException {
		rs = stmt.executeQuery( "SELECT village_id, population, x, y, ruler_id, name " +
				"FROM village " +
				"WHERE militia >= " + turn );
		while( rs.next() ) {
			int villageId = rs.getInt( "village_id" );
			AgesOfStrifeServer.log.debug( "Militia from: " + villageId + " is looking for enemies nearby" );
			int rulerId = rs.getInt( "ruler_id" );
			int population = rs.getInt( "population" );
			int x = rs.getInt( "x" );
			int y = rs.getInt( "y" );
			int factionId = -1;
			String factionName = "";
			String villageName = rs.getString( "name" );
			String rulerName = "";
			boolean first = true;
			boolean friendly = false;
			boolean enemy = false;
			int lastEnemyArmyId = -1;
			rs2 = stmt2.executeQuery( "SELECT army_id, ruler_id, scout, infantry, cavalry, artillery, name, officer_id " +
					"FROM army " +
					"WHERE actual_x + 0.5 > " + x + " AND actual_x - 0.5 < " + x + 
						" AND actual_y + 0.5 > " + y + " AND actual_y - 0.5 < " + y + " " +
						"AND scout + infantry + cavalry + artillery > 0 " +
					"ORDER BY RAND()" );
			while( rs2.next() ) {
				if( first ) {
					rs3 = stmt3.executeQuery( "SELECT faction.faction_id, name " +
							"FROM faction_member " +
							"JOIN faction ON faction_member.faction_id = faction.faction_id " +
							"WHERE invited = 0 AND requested = 0 AND ruler_id = " + rulerId );
					if( rs3.next() ) {
						factionId = rs3.getInt( 1 );
						factionName = rs3.getString( 2 );
					}
					rs3 = stmt3.executeQuery( "SELECT name " +
							"FROM ruler " +
							"WHERE ruler_id = " + rulerId );
					if( rs3.next() ) {
						rulerName = rs3.getString( 1 );
					}
					first = false;
				}
				int armyRulerId = rs2.getInt( "ruler_id" );
				int armyFactionId = -1;
				rs3 = stmt3.executeQuery( "SELECT faction_id " +
						"FROM faction_member " +
						"WHERE invited = 0 AND requested = 0 AND ruler_id = " + armyRulerId );
				if( rs3.next() ) {
					armyFactionId = rs3.getInt( "faction_id" );
				}
				
				if( ( armyFactionId != -1 && armyFactionId != factionId ) || armyFactionId == -1 ) {
					enemy = true;
					lastEnemyArmyId = rs2.getInt( "army_id" );
				}
				else {
					friendly = true;
				}
			}
			
			if( enemy && !friendly ) {
				rs2 = stmt2.executeQuery( "SELECT army_id, ruler_id, scout, infantry, cavalry, artillery, name, officer_id " +
						"FROM army " +
						"WHERE army_id = " + lastEnemyArmyId );

				if( rs2.next() ) {
					int armyRulerId = rs2.getInt( "ruler_id" );
					int armyFactionId = -1;
					String armyFactionName = "";
					rs3 = stmt3.executeQuery( "SELECT faction.faction_id, name " +
							"FROM faction_member " +
							"JOIN faction ON faction_member.faction_id = faction.faction_id " +
							"WHERE invited = 0 AND requested = 0 AND ruler_id = " + armyRulerId );
					if( rs3.next() ) {
						armyFactionId = rs3.getInt( "faction_id" );
						armyFactionName = rs3.getString( "name" );
					}
					// There is a hostile army in range of the militia and no friendly army to fight
					// So there will be battle!
					int armyId = rs2.getInt( "army_id" );
					int scouts = rs2.getInt( "scout" );
					int infantry = rs2.getInt( "infantry" );
					int cavalry = rs2.getInt( "cavalry" );
					int artillery = rs2.getInt( "artillery" );
					int officerId = rs2.getInt( "officer_id" );
					String armyName = rs2.getString( "name" );
					AgesOfStrifeServer.log.debug( "Militia from " + villageId + " found enemy " + armyName + " (" + armyId + ")" );
					String armyRulerName = "";
					int scoutsBefore = scouts;
					int infantryBefore = infantry;
					int cavalryBefore = cavalry;
					int artilleryBefore = artillery;
					int experienceGained = 0;
					
					boolean militiaDestroyed = false;
					int armyAttack = scouts * 2 + infantry * 3 + cavalry * 15 + artillery * 24;
					int militia = ( int ) ( population * 0.25 );
					int militiaAfter = militia - ( int ) ( armyAttack * 0.5 ); 
					if( militiaAfter < 0 ) {
						militiaAfter = 0;
					}
					if( militiaAfter <= population * 0.025 ) {
						militiaDestroyed = true;
					}
					int count = 0;
					int add = ( int ) ( militia * 0.075 );
					while( add > 0 && count < 5 ) {
						scouts -= add;
						if( scouts < 0 ) {
							add = -( int ) ( scouts * 0.7 );
							scouts = 0;
						}
						else {
							add = 0;
						}
						if( count == 0 ) {
							add += ( int ) ( militia * 0.16 );
						}
						infantry -=  add;
						if( infantry < 0 ) {
							add = -( int ) ( infantry * 0.19 );
							infantry = 0;
						}
						else {
							add = 0;
						}
						if( count == 0 ) {
							add += ( int ) ( militia * 0.032);
						}
						cavalry -= add;
						if( cavalry < 0 ) {
							add = -( int ) ( cavalry * 0.65 );
							cavalry = 0;
						}
						else {
							add = 0;
						}
						if( count == 0 ) {
							add += ( int ) ( militia * 0.02 );
						}
						artillery -= add;
						if( artillery < 0 ) {
							add = -artillery * 12;
							artillery = 0;
						}
						else {
							add = 0;
						}
						count ++;
					}
					
					experienceGained =  ( scoutsBefore - scouts ) * 32 + 
										( infantryBefore - infantry ) * 48 + 
										( cavalryBefore - cavalry ) * 256 + 
										( artilleryBefore - artillery ) * 400;
					int armyExperienceGained = ( int ) ( experienceGained * 0.5 );
					
					rs3 = stmt3.executeQuery( "SELECT name " +
							"FROM ruler " +
							"WHERE ruler_id = " + armyRulerId );
					if( rs3.next() ) {
						armyRulerName = rs3.getString( 1 );
					}

					newsItem.clear();
					newsItem.addTitleText( "Battle with a militia", true );
					newsItem.addText( "There has been a battle between an army and a militia at", true );
					newsItem.addText( " <a href=\"../operations/map.php?x=" + ( x - 20 ) + "&y=" + ( y - 20 ) + "\">" + villageName + "</a>.", true );
										
					newsItem.addText( "\n\n<table class=\"news-table\"><tr><th colspan=\"4\">" + armyName + " ", false );
					newsItem.addText( "under command of", true );
					newsItem.addText( " " + armyRulerName, false );
					if( armyFactionId != -1 ) {
						newsItem.addText( " ", false );
						newsItem.addText( "from", true );
						newsItem.addText( " " + armyFactionName, false );
					}
					
					newsItem.addText( "</th></tr><tr class=\"even\"><td>", false );
					newsItem.addText( "Units", true );
					newsItem.addText( "</td><td align=\"right\">", false );
					newsItem.addText( "Before", true );
					newsItem.addText( "</td><td align=\"right\">", false );
					newsItem.addText( "After", true );
					newsItem.addText( "</td><td align=\"right\">", false );
					newsItem.addText( "Lost", true );
					newsItem.addText( "</td></tr>", false );

					newsItem.addText( "<tr><td>", false ); 
					newsItem.addText( "Scouts", true );
					newsItem.addText( "<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + scoutsBefore ) + "</strong></td>", false );
					newsItem.addText( "<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + scouts ) + "</strong></td>", false );
					newsItem.addText( "<td align=\"right\"><strong class=\"scouts\">" + Utils.formatNumber( "" + ( scoutsBefore - scouts ) ) + "</strong></td></tr>", false );
					
					newsItem.addText( "<tr class=\"even\"><td>", false ); 
					newsItem.addText( "Infantry", true );
					newsItem.addText( "<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + infantryBefore ) + "</strong></td>", false );
					newsItem.addText( "<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + infantry ) + "</strong></td>", false );
					newsItem.addText( "<td align=\"right\"><strong class=\"infantry\">" + Utils.formatNumber( "" + ( infantryBefore - infantry ) ) + "</strong></td></tr>", false );
					
					newsItem.addText( "<tr><td>", false ); 
					newsItem.addText( "Cavalry", true );
					newsItem.addText( "<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalryBefore ) + "</strong></td>", false );
					newsItem.addText( "<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + cavalry ) + "</strong></td>", false );
					newsItem.addText( "<td align=\"right\"><strong class=\"cavalry\">" + Utils.formatNumber( "" + ( cavalryBefore - cavalry ) ) + "</strong></td></tr>", false );

					newsItem.addText( "<tr class=\"even\"><td>", false ); 
					newsItem.addText( "Artillery", true );
					newsItem.addText( "<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + artilleryBefore ) + "</strong></td>", false );
					newsItem.addText( "<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + artillery ) + "</strong></td>", false );
					newsItem.addText( "<td align=\"right\"><strong class=\"artillery\">" + Utils.formatNumber( "" + ( artilleryBefore - artillery ) ) + "</strong></td></tr></table><br />", false );

					newsItem.addText( "\n<table class=\"news-table\"><tr><th colspan=\"4\">", false );
					newsItem.addText( "A militia from", true );
					newsItem.addText( " " + villageName + " ", false );
					newsItem.addText( "controlled by", true );
					if( rulerName == "" ) {
						newsItem.addText( " ", false );
						newsItem.addText( "independents", true );
					}
					else {
						newsItem.addText( " " + rulerName, false );
					}
					if( factionId != -1 ) {
						newsItem.addText( " ", false );
						newsItem.addText( "from", true );
						newsItem.addText( " " + factionName, false );
					}
					
					newsItem.addText( "</th></tr><tr class=\"even\"><td>", false );
					newsItem.addText( "Units", true );
					newsItem.addText( "</td><td align=\"right\">", false );
					newsItem.addText( "Before", true );
					newsItem.addText( "</td><td align=\"right\">", false );
					newsItem.addText( "After", true );
					newsItem.addText( "</td><td align=\"right\">", false );
					newsItem.addText( "Lost", true );
					newsItem.addText( "</td></tr>", false );

					newsItem.addText( "<tr><td>", false ); 
					newsItem.addText( "Militia", true );
					newsItem.addText( "<td align=\"right\"><strong class=\"population\">" + Utils.formatNumber( "" + militia ) + "</strong></td>", false );
					newsItem.addText( "<td align=\"right\"><strong class=\"population\">" + Utils.formatNumber( "" + militiaAfter ) + "</strong></td>", false );
					newsItem.addText( "<td align=\"right\"><strong class=\"population\">" + Utils.formatNumber( "" + ( militia - militiaAfter ) ) + "</strong></td></tr></table>", false );
					
					if( militiaDestroyed ) {
						// Remove militia status and allow it to reform in 24 turns
						newsItem.addText( "\n\n", false ); 
						newsItem.addText( "The militia has been scattered.", true );
						
						stmtUpdate.execute( "UPDATE village " +
								"SET population = population - " + ( militia - militiaAfter ) + ", " + 
								"militia = " + turn + " " + 
								"WHERE village_id = " + villageId );
					}
					else {
						// The militia has survived the battle
						stmtUpdate.execute( "UPDATE village " +
								"SET population = population - " + ( militia - militiaAfter ) + " " + 
								"WHERE village_id = " + villageId );
					}
					
					newsItem.insert( armyRulerId, 1, turn, date );
					newsItem.insert( rulerId, 1, turn, date );
					
					// Update the officer, army and ruler of the army
					stmtUpdate.execute( "UPDATE " +
							"officers " +
							"SET experience = experience + " + armyExperienceGained + " " +
							"WHERE officer_id = " + officerId );
					stmtUpdate.execute( "UPDATE ruler " +
							"SET scouts_lost = scouts_lost + " + ( scoutsBefore - scouts ) + "," +
							"infantry_lost = infantry_lost + " + ( infantryBefore - infantry ) + "," +
							"cavalry_lost = cavalry_lost + " + ( cavalryBefore - cavalry ) + "," +
							"artillery_lost = artillery_lost + " + ( artilleryBefore - artillery ) + "," +
							"experience = experience + " + armyExperienceGained + " " + 
							"WHERE ruler_id = " + armyRulerId );
					if( scouts + infantry + cavalry + artillery == 0 ) {
						stmtUpdate.execute( "DELETE FROM army_orders " +
								"WHERE army_id = " + armyId );
						stmtUpdate.execute( "DELETE FROM army " +
								"WHERE army_id = " + armyId );
					}
					else {
						stmtUpdate.execute( "UPDATE army " +
								"SET scout = " + scouts + ", infantry = " + infantry + ", cavalry = " + cavalry + ", artillery = " + artillery + " " +
								"WHERE army_id = " + armyId );
					}
					
					// Experience for the militia owner
					stmtUpdate.execute( "UPDATE ruler " +
							"SET scouts_killed = scouts_killed + " + ( scoutsBefore - scouts ) + "," +
							"infantry_lost = infantry_killed + " + ( infantryBefore - infantry ) + "," +
							"cavalry_killed = cavalry_killed + " + ( cavalryBefore - cavalry ) + "," +
							"artillery_killed = artillery_killed + " + ( artilleryBefore - artillery ) + "," +
							"experience = experience + " + experienceGained + " " + 
							"WHERE ruler_id = " + rulerId );
				}
			}
		}
	}
}
